二叉排序树(二叉搜索树)

来源:互联网 发布:数据库的核心 编辑:程序博客网 时间:2024/06/02 07:31

动态查找表的一种理想数据结构。

二叉排序树的定义是:二叉排序树T是一棵树,它或者是空,或者具备一下三条性质:

(1)、如果T的根节点的左子树非空,其左子树所有结点的值均小于T的根节点的值

(2)、如果T的根节点的右子树非空,其右子树所有结点的值均大于T的根节点的值
(3)、T的根结点的左右子树均为二叉排序树

下面是代码:

文件"tree.h"

#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;elsef->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;}elseInsert_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;}elseInsert_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;elseq->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;elsef->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);}}};

主函数"main.cpp"

#include"tree.h"int main(){Bin_Sort_Tree tree;BSTnode *root=NULL;cout<<"_____建立二叉排序树____"<<endl;tree.Create_BSTree(root);cout<<"前序遍历二叉树为:";tree.PreOrder_Traverse(root);cout<<endl;cout<<"中序遍历二叉树为:";tree.InOrder_Traverse(root);cout<<endl;cout<<"后序遍历二叉树为:";tree.PostOrder_Traverse(root);cout<<endl;cout<<"层次遍历二叉树为:";tree.LevelOrder_Traverse(root);cout<<endl;int data;BSTnode *f=NULL;BSTnode *p=NULL;cout<<"输入你要搜索的结点的值:";cin>>data;if(tree.Search_BST(root,data,f,p)){cout<<"你所搜索的结点地址为:"<<p<<endl;cout<<"他的双亲结点值为:"<<tree.Get_data(f)<<endl;}elsecout<<"树中没有你要找的结点"<<endl;cout<<"输入你要删除的结点的值:";cin>>data;tree.Delete_BST(root,data);cout<<"删除后的二叉树的中序遍历为:";tree.InOrder_Traverse(root);cout<<endl;cout<<"输入你要插入树中的值:";cin>>data;tree.Insert_BST_2(root,data);cout<<"插入后,树的中序遍历为:";tree.InOrder_Traverse(root);cout<<endl;return 0;}

下面是测试结果

_____建立二叉排序树____输入二叉排序树的元素,输入-1代表结束输入:5 7 3 2 9 4 8 8 1 10 -1____建树完成____前序遍历二叉树为:5  3  2  1  4  7  9  8  10中序遍历二叉树为:1  2  3  4  5  7  8  9  10后序遍历二叉树为:1  2  4  3  8  10  9  7  5层次遍历二叉树为:5  3  7  2  4  9  1  8  10输入你要搜索的结点的值:7你所搜索的结点地址为:00380D18他的双亲结点值为:5输入你要删除的结点的值:10结点删除成功删除后的二叉树的中序遍历为:1  2  3  4  5  7  8  9输入你要插入树中的值:6插入后,树的中序遍历为:1  2  3  4  5  6  7  8  9Press any key to continue

按照一开始建树时的输入,生成的树为: