动态查找之二叉排序树

在查找这一章,我认为静态查找都比较简单,所以就跳过了,二叉排序树以及与之相关的一些数据结构还是有一定意义的。二叉排序树:左子树小于根节点,右子树大于根节点。这个原理很简单,就上面几行几个字,实现起来代码也很简洁,使用递归调用。在节点删除的时候,到时有不同的情况,需要注意一下。
(1)若待删除节点是叶子节点,则之间删除,修改下父节点的指针就可以了。
(2)若只有左子树或右子树,直接将其子树接到待删除节点的父节点后面就可以了。
(3)若既有左子树又有右子树的,相对就麻烦一些。其中有两种方法:第一,将左子树接到其父节点上,然后将其右子树接到左子树的最右端,这是因为右子树的节点都是比左子树大的,所以将右子树接到左子树最大的位置,也就是最右端,依次也可以将右子树接到父节点上,然后将左子树接到右子树的最左端。 第二,不改变左子树和右子树,为了保持排序树的特性,将左子树最大值节点替换待删除节点,或者是讲右子树最小值节点代替之。
#include <stdio.h>
#include <stdlib.h>
#include "Search.h"
//查找二叉排序树
//第一个参数:查询节点
//第二个参数:查找的键值
// 第三个参数:查找节点的父节点
//第四个参数:用于返回查找到的节点 
int SearchBST(const pNode T,const ElemType key,pNode f,pNode &p)
{
if(!T){ p = f; return 0; }       //节点不存在,返回最后一个节点,在数据插入其后 
else if(key == T->data){p = T; return true; }  //该节点在排序树中 
else if(key > T->data) return SearchBST(T->rchild,key,T,p);    //向右子树查找 
else return SearchBST(T->lchild,key,T,p);          //向左子树查找 
}
//排序树中插入节点 
//待插入节点的父节点,插入元素 
int InsertBST(pNode T,const ElemType e)
{
pNode s;
s=(pNode)malloc(sizeof(tNode));
if(!s) return false;
s->data = e;
s->lchild = s->rchild = NULL;  //到此构造节点结束 
//这里在调试的时候要考虑树为空时的插入
    //所以在初始化头结点的时候用255赋值给data
    //左子树作为第一个节点 
if(e < T->data)  T->lchild = s;    //在此进行插入 
else T->rchild = s;
return true;
}
//排序树删除一个节点 
//在此用引用的好处就是可以改变传递进来指针的值 
int DeleteBST(pNode &T,ElemType key)
{
if(!T) return false;       //节点不存在 
else 
{
if(key == T->data) return Delete( T );   //删除本节点 
else if(key > T->data) return DeleteBST(T->rchild, key); //到右子树递归 
else return DeleteBST( T->lchild,key);           //到左子树递归 
}
}
//进行删除操作 
int Delete(pNode & T)
{
pNode p;
if(!T->rchild)     //右子树有空,直接将左子树接到上面 
{
p = T;
T = T->lchild;
free(p);
}
else if(!T->lchild)    //左子树为空。直接将右子树接到上面 
{
p = T;
T = T->rchild;
free(p);
}
else   //左右子树都不为空 
{
pNode s;     //保存左子树的最大值节点 
p = T;       //保存s的父节点 
s = T->lchild;
while(s->rchild)     //根据特性,最右的节点最大 
{
p = s;
s= s->rchild;
}
T->data = s->data;   //待删除节点交换信息,相当于两节点置换 
//当s的父节点就是待删除节点时,说明s就是T的左孩子
            // 此时修改的是T的左孩子
            //否则修改s父节点的右孩子 
if(p != T) p->rchild = s->lchild;
else p->lchild = s->lchild;
free(s);
}
return true;
}


int main()
{
tNode head;
head.lchild = NULL;        //树的第一个节点 
head.rchild = NULL;
head.data   = 0xFF;        //可用于统计元素个数,在实现时为了操作简单,存放length-1; 
while(1)
{
ElemType temp;
//pNode f = head.lchild;
pNode p = NULL;
printf("input the key:");
scanf("%d",&temp);
if(SearchBST(head.lchild,temp,&head,p))
{
printf("元素:%d存在树中!\n",p->data);
}
else
{
InsertBST(p,temp);
head.data++;
printf("I insert the key!\n");
}
}
return 0;
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值