二叉搜索树
二叉排序树又称“二叉查找树”、“二叉搜索树”。
二叉排序树:或者是一棵空树,或者是具有下列性质的二叉树:
1. 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值;
2. 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值;
3. 它的左、右子树也分别为二叉排序树。
二叉排序树通常采用二叉链表作为存储结构。中序遍历二叉排序树可得到一个依据关键字的有序序列,一个无序序列可以通过构造一棵二叉排序树变成一个有序序列,构造树的过程即是对无序序列进行排序的过程。每次插入的新的结点都是二叉排序树上新的叶子结点,在进行插入操作时,不必移动其它结点,只需改动某个结点的指针,由空变为非空即可。搜索、插入、删除的时间复杂度等于树高,期望O(logn),最坏O(n)(数列有序,树退化成线性表,如右斜树)。
查找:
思路:①若二叉树为空,则找不到,②先与根比较,相等则找到,否则若小于根则在左子树上继续查找,否则在右子树上继续查找。
递归算法:
BstTree BstSearch ( BstTree bst, DataType x )
{
if ( bst==NULL )
return NULL;
else if ( bst->data==x )
return bt;
else if ( x<bst->data )
return BstSearch ( bst->lchild, x);
else
return BstSearch ( bst->rchild, x);
}
非递归算法:
BstTree BstSearch ( BstTree bst, DataType x)
{
p =bst;
while ( p ) {
if ( p->data==x )
return p;
else if ( x<p->data )
p = p->lchild;
else
p = p->rchild;
}
return NULL; // not found
}
插入:
思路:先查找,若找不到则插入结点作为最后访问的叶子结点的孩子。
新插入的结点总是叶子。
建立:
经过一系列插入操作可以建立二叉排序树。
给定关键字序列,建立二叉排序树。方法:①开始二叉树为空,②对每一个关键字,先进行查找,如果已存在,则不作任何处理,否则插入。
一句话,“从空树开始,每次插入一个关键字”。
删除:要注意删除结点为根节点的情况
#include <iostream>
using namespace std;
struct node
{
int data;
node *lchild,*rchild;
};
//插入
void Insert(node *&T,int data)
{
if(T==NULL)//空树时
{
T=new node;
T->data=data;
T->lchild=NULL;
T->rchild=NULL;
}
else
{
node *p=T,*f=NULL;
while(p!=NULL)//查找要插入的位置
{
if(p->data==data)
return;
f=p;//记录父结点,用来最后指向新的叶子结点
if(data<p->data)
p=p->lchild;
else
p=p->rchild;
}
p=new node ;//产生一个叶子结点
p->data=data;
p->lchild=NULL;
p->rchild=NULL;
if(data<f->data)//将新的叶子结点加入到原树中
f->lchild=p;
else
f->rchild=p;
}
}
//建立BST
node* Create()//生成二叉排序树
{
node *T=NULL;
int i;
cin>>i;
while(i!=-1)
{
Insert(T,i);
cin>>i;
}
return T;
}
//中序遍历
void Print(node *T)//中序遍历
{
if(T!=NULL)
{
Print(T->lchild);
cout<<T->data<<' ';
Print(T->rchild);
}
}
//查找
void Find(node *T,int data,node *&f,node *&p)//返回多个值,将返回参数按引用或指针方式使用,不能传值
{
if(T==NULL)
return ;
else
{
p=T;
while(p)
{
if(p->data==data)
{
//cout<<"find data= "<<p->data<<endl;
return ;
}
f=p;//如果查找的是根节点,则f为初始值NULL,否则为p的父结点
if(data<p->data)
{
p=p->lchild;
}
else
p=p->rchild;
}
}
}
//删除结点
void Delete(node * &T,int data)
{
node * f=NULL,*p=NULL;
if(T==NULL)//空树
return;
Find(T,data,f,p);
if(p==NULL)//没有找到
return;
if(p->lchild==NULL && p->rchild==NULL)//删除叶子结点
{
if(f)//非根结点
{
if(f->lchild==p)
{
f->lchild=NULL;
}
else
{
f->rchild=NULL;
}
}
else
T=NULL;
delete p;
}
else if(p->lchild==NULL)
{
if(f)//非根结点
{
if(f->lchild==p)
{
f->lchild=p->rchild;
}
else
{
f->rchild=p->rchild;
}
}
else
T=p->rchild;
delete p;
}
else//删除的结点含有左右子树:从待删除结点的左子树中选择最大值,交换,删除左子树中的最大值结点
{
node *p1=NULL,*p2=NULL;
p1=p->lchild;//指向待删除结点的左子树
p2=p1;
while(p1!=NULL && p1->rchild!=NULL)//找最大值,p1所指向的为最大值
{
p2=p1;
p1=p1->rchild;
}
p->data=p1->data;//交换
p2->rchild=NULL;//删除
delete p1;
}
}
void main()
{
node *T=Create();
Print(T);
cout<<endl;
Insert(T,99);
Print(T);
cout<<endl;
node *f=NULL,*p=NULL;
Find(T,99,f,p);
if(p!=NULL)
cout<<p->data<<endl;
int i;
cout<<"输入要删除的数"<<endl;
cin>>i;
Delete(T,i);
cout<<endl;
Print(T);
system("pause");
}
#include <iostream>
using namespace std;
struct node
{
int data;
node *left;
node *right;
};
void Inseart(node *&T,int data)
{
if(T==NULL)
{
T=new node;
T->data=data;
T->left=NULL;
T->right=NULL;
}
else
{
node *f=NULL,*p=T;
while(p)
{
f=p;
if(data==p->data)
return;
else if(data<p->data)
p=p->left;
else
p=p->right;
}
p=new node ;
p->data=data;
p->left=NULL;
p->right=NULL;
if(data<f->data)
f->left=p;
else
f->right=p;
}
}
void Create(node *&T)
{
int data;
cin>>data;
while(data!=-1)
{
Inseart(T,data);
cin>>data;
}
}
void Print(node *T)
{
if(T)
{
Print(T->left);
cout<<T->data<<endl;
Print(T->right);
}
}
void Search(node *T,int data ,node * &f,node * &p)
{
if(T==NULL)
return;
p=T;
while(p)
{
if(data==p->data)
{
return;
}
f=p;
if(data<p->data)
{
p=p->left;
}
else
p=p->right;
}
if(p==NULL)
{
cout<<"not find"<<endl;
p=f=NULL;
}
}
void Delete(node * &T,int data)
{
node *f=NULL,*p=T;
Search(T,data,f,p);
if(p==NULL)
return;
if(p->left==NULL && p->right==NULL)
{
if(f==p)
{
T=NULL;
delete p;
}
else
{
if(f->left==p)
f->left=NULL;
else
f->right=NULL;
delete p;
}
}
else if(p->left==NULL)//有右子树
{
if(f==p)//要删除的是根结点
{
T=p->right;
delete p;
}
else
{
if(f->left==p)
f->left=p->right;
else
f->right=p->right;
}
}
else if(p->right==NULL)//有左子树
{
if(f==p)
{
T=p->left;
delete p;
}
else
{
if(f->left==p)
f->left=p->left;
else
f->right=p->left;
}
}
else//有左右子树
{
node *pmax=p->left,*pre=p;
while(pmax!=NULL && pmax->right!=NULL)
{
pre=pmax;
pmax=pmax->right;
}
swap(pmax->data,p->data);
delete pmax;
if(p==pre)//左子树里没有右子树
pre->left=NULL;
else
pre->right=NULL;
}
}
void main()
{
node* T=NULL;
Create(T);
Print(T);
int data;
cin>>data;
Delete(T,data);
cout<<"-------------------"<<endl;
Print(T);
system("pause");
}