二叉查找树(二叉搜索树,二叉排序树):
二叉排序树或者是一棵空树,或者是具有下列性质的二叉树:
(1)若左子树不空,则左子树上所有结点的值均小于它的根结点的值;
(2)若右子树不空,则右子树上所有结点的值均大于它的根结点的值;
(3)左、右子树也分别为二叉排序树;
(4)没有键值相等的节点。
其实总结下来简单来说就是,一个没有重复值的,左边比根小,右边比根大的二叉树
为了方便理解,我把二叉查找树的实现分为1,查;2,增;3,删;
查找:
bool SearchTree(BiTree T,int key,BiTree pre,BiTree &n){
if(!T){ //如果树为空,返回false,且把n赋值给pre,方便后面的插入操作
n=pre;
return false;
}
else if(key==T->data){
n=T; //找到了就把找到的给n;
return true;
}
if(key<T-data)
SearchTree(T->lchild,key,T,n);
else
SearchTree(T->rchild,key,T,n);
}
n参数是代表他的父节点。不论是能否查找到,都会有一个返回他父亲节点的参数,方便后面的删除修改增加。
增加:
bool InsertBST(BiTree &T,int k){
BiTNode* p;
if(!SearchTree(T,k,NULL,p){ //二叉查找树不能有重复的键,只有找不到才能进行插入
BiTNode* temp=new BiTNode;
temp->data=k;
temp->lchild=temp->rchild=NULL;
if(!p){ //只有树为空,p才会空,直接根节点等于temp.
T=temp;
}
else{
if(k>p->data){ //如果不为空,加入的k值就和p值相比较
p->rchild=temp;
}
else
p->lchild=temp;
}
return true;
}
else{
return false;
}
}
删除:
删除的话,总共有三种情况。
1,要删除的节点只有左子树;2,要删除的节点只有右子树;3,要删除的节点左右子树都有;
1,2种情况很简单,只需要把父亲节点接到它的子节点去。
第三种情况就要稍微复杂些,需要找到比这个要删除的节点大且距离这个节点最近的数(注意,所说的最近的意思是比这个数大却又大得有限的意思)。
所以先找到这个要删除的节点,然后找他的右子树,然后在右子树下无限找它的左子树。然后这个将这个左子树的值覆盖到要删除的节点上,然后将这个左子树free掉就完成了。
bool DeleElement(BiTree&T,int key)
{
if(!T)
{
return 0; //树是空树的话就返回假
}
if(T->data==key)
{
BitNode*s,*p;
if(T->rchild==NULL) //只有右子树,情况2
{
s=T;
T=T->lchild;
free(s);
}
else if(T->lchild==NULL)
{
s=T; //只有左子树,情况1
T=T->rchild;
free(s);
}
else
{ //情况3,左右子树都有
p=T;
s=T->rchild;
while (s->lchild)
{
p=s; //找到所要删除节点的后继,那就是他的右孩子的左孩子
s=s->lchild;
}
T->data=s->data; //用删除节点的后继替换所删除的节点
if(p!=T)
{
p->lchild=NULL; //所删除的节点的右孩子不是叶结点
}
else
p->rchild=NULL; //所删除的节点的右孩子是叶节点
free(s);
}
return 1;
}
else if(key<T->data)
DeleElement(T->lchild,key); //去和他的左子树根去比较
else
DeleElement(T->rchild,key); //去和他的右子树根去比较
}