动态查找表的一种理想数据结构。
二叉排序树的定义是:二叉排序树T是一棵树,它或者是空,或者具备一下三条性质:
(1)、如果T的根节点的左子树非空,其左子树所有结点的值均小于T的根节点的值
(2)、如果T的根节点的右子树非空,其右子树所有结点的值均大于T的根节点的值
(3)、T的根结点的左右子树均为二叉排序树
下面是代码:
文件"tree.h"
[cpp]
#include<iostream> #include<stack> #include<queue> using namespace std; #define MAX_NODE_NUM 20 //树结点最大值 class Bin_Sort_Tree; //树结点 class BSTnode { int tag;//后序遍历作为访问标志 int data; BSTnode *lchild; BSTnode *rchild; friend class Bin_Sort_Tree; }; //二叉排序树 class Bin_Sort_Tree { public: int Get_data(BSTnode *p) { return p->data; } bool Search_BST(BSTnode *T,int a,BSTnode *&f,BSTnode *&p) { /*----------------------------- /在树中查找值为a的结点,查找到 /了,用p保存该结点地址,f指向 /p的双亲结点 /-----------------------------*/ p=T; while(p) { if(p->data==a) return true; else if(p->data>a) { f=p; p=p->lchild; } else { f=p; p=p->rchild; } } return false; } //将值为a的结点插入树中,若值已存在,就不插入 void Insert_BST_1(BSTnode *&T,int a) { BSTnode *f=NULL; BSTnode *p=NULL; if(Search_BST(T,a,f,p)) return; //树中已有值相同结点,不插入 else { BSTnode *s=new BSTnode; s->data=a; s->lchild=s->rchild=NULL; if(s->data>f->data) f->rchild=s; else f->lchild=s; } } void Insert_BST_2(BSTnode *&T,int a) //插入算法递归实现 { if(!T) { cout<<"树为空"<<endl; return; } if(T->data>a) { if(!T->lchild) { T->lchild=new BSTnode; T->lchild->data=a; T->lchild->lchild=NULL; T->lchild->rchild=NULL; return; } else Insert_BST_2(T->lchild,a); } if(T->data<a) { if(!T->rchild) { T->rchild=new BSTnode; T->rchild->data=a; T->rchild->lchild=NULL; T->rchild->rchild=NULL; return; } else Insert_BST_2(T->rchild,a); } } void Create_BSTree(BSTnode *&T) //建树 { cout<<"输入二叉排序树的元素,输入-1代表结束输入:"; int num[MAX_NODE_NUM]; int a,i=0; while(cin>>a && a!=-1) { num[i]=a; i++; } if(num[0]==-1) { cout<<"排序树为空"<<endl; return; } int k=i; T=new BSTnode; T->data=num[0]; T->lchild=T->rchild=NULL; for(i=1;i<k;i++) Insert_BST_1(T,num[i]); cout<<"____建树完成____"<<endl; } void Delete_BST(BSTnode *&T,int a)//删除结点值为a的结点 { /*--------------------------------------------------------- / 从树中删除一个节点后,要保证删后的树还是一棵二叉排序树, / 删除前,首先是在树中查找是否有这个结点,用p指向该结点, / 用f指向p的双亲结点,这个结点在树中的位置有下面四种情况: / / 1:如果p指向的结点是叶子结点,那么直接将f指针的左子树或者 / 右子树置空,然后删除p结点即可。 / / 2:如果p指向的结点是只有左子树或右子树,那么只需要让p结点 / 原来在f中的位置(左子树或右子树)用p的子树代替即可。 / / 3:如果p所指向的结点是根节点,那么直接将根节点置空 / / 4:如果p所指向的结点左右子树都非空,为了删除p后原序列的顺 / 序不变,就需要在原序列中先找出p的直接前驱(或者直接后继) / 结点用那个结点的值来代替p结点的值,然后再删掉那个直接前 / 驱(或者直接后继)结点。 / 在中序遍历序列中找结点的直接前驱的方法是顺着结点的左孩子 / 的右链域开始,一直到结点右孩子为空为止。 /---------------------------------------------------------*/ BSTnode *f=NULL; BSTnode *p=NULL; BSTnode *q=NULL; BSTnode *s=NULL; if(Search_BST(T,a,f,p)) { if(p->lchild && p->rchild) { q=p; s=p->lchild; while(s->rchild) { q=s; s=s->rchild; } p->data=s->data; //s指向要删除结点的直接前驱,且s是一定没有右子树的 if(q!=p) q->rchild=s->lchild; else q->lchild=s->lchild;//这种情况是,q的左子树的右子树为空时 delete s; cout<<"结点删除成功"<<endl; return ; } else { if(!p->lchild) //左子树为空 { q=p; p=p->rchild; } else //右子树为空 { q=p; p=p->lchild; } //下面将p所指向的子树连接到f所指(被删结点的双亲)的结点上 if(!T) //被删的结点为根节点 T=p; else if(q==f->lchild) f->lchild=p; else f->rchild=p; delete q; cout<<"结点删除成功"<<endl; return; } } else { cout<<"要删除的结点不存在"<<endl; return ; } } //下面是二叉树的四种遍历方式,都是非递归方式实现 void PreOrder_Traverse(BSTnode *T) //前序遍历 { stack<BSTnode *> s; BSTnode *p; p=T; while(p || !s.empty()) { if(p) { cout<<p->data<<" "; s.push(p); p=p->lchild; } else { p=s.top(); s.pop(); p=p->rchild; } } } void InOrder_Traverse(BSTnode *T) //中序遍历 { stack<BSTnode *> s; BSTnode *p=T; while(p || !s.empty()) { if(p) { s.push(p); p=p->lchild; } else { p=s.top(); s.pop(); cout<<p->data<<" "; p=p->rchild; } } } void PostOrder_Traverse(BSTnode *T) //后序遍历 { stack<BSTnode *> s; BSTnode *p=T; while(p || !s.empty()) { if(p) { p->tag=0; s.push(p); p=p->lchild; } else { p=s.top(); if(p->tag) { cout<<p->data<<" "; s.pop(); p=NULL; } else { p->tag=1; p=p->rchild; } } } } void LevelOrder_Traverse(BSTnode *T) //层次遍历 { queue<BSTnode *> q; BSTnode *p=T; q.push(p); while(!q.empty()) { p=q.front(); q.pop(); cout<<p->data<<" "; if(p->lchild) q.push(p->lchild); if(p->rchild) q.push(p->rchild); } } };