动态查找表的一种理想数据结构。
二叉排序树的定义是:二叉排序树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;
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);
}
}
};
主函数"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;
}
else
cout<<"树中没有你要找的结点"<<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 9
Press any key to continue
按照一开始建树时的输入,生成的树为: