二叉排序(查找)树及查找,插入,删除操作

  动态查找树表
1  二叉排序树
1.二叉排序树定义
二叉排序树(Binary Sort Tree)或者是一棵空树;或者是具有下列性质的二叉树:
⑴ 若左子树不空,则左子树上所有结点的值均小于根结点的值;若右子树不空,则右子树上所有结点的值均大于根结点的值。
⑵ 左右子树也都是二叉排序树。
通常,取二叉链表作为二叉排序树的存储结构。
2.二叉排序树查找过程
从其定义可见,二叉排序树的查找过程是一个递归过程,具体为:
① 若查找树为空,查找失败。
② 查找树非空,将给定值 key 与查找树的根结点关键码比较。
③ 若相等,查找成功,结束查找过程,否则,
a.当给 key 小于根结点关键码,查找将在以左孩子为根的子树上继续进行,转①
b.当给 key 大于根结点关键码,查找将在以右孩子为根的子树上继续进行,转①
●递归算法:
BiTree SearchBST(BiTree b, KeyType key) {
 if(!b)      return NULL;    //查找失败
 else if(b-> data.key ==key)       return b; //查找成功
 else if(key<b-> data.key)
              return SearchBST(b->lchild,key); //在左子树中继续查找
       else return SearchBST(b->rchild,key); //在右子树中继续查找
}
由值相同的 n 个关键字,构造所得的不同形态的各棵二叉排序树的平均查找长度的值不同,甚至可能差别很大。
3.二叉排序树插入操作和构造一棵二叉排序树
在二叉排序树中插入一个结点的过程:设待插入结点的关键码为 key,为将其插入,先要在二叉排序树中进行查找,若查找成功,按二叉排序树定义,待插入结点已存在,不用插入;查找不成功时,则插入之。因此,新插入结点一定是作为叶子结点添加上去的。构造一棵二叉排序树就是逐个插入结点的过程。
void InsertBST(BiTree &b, KeyType key) {
 BiTree s;
 if (bt==NULL) { // 递归结束条件
  s=(BiTNode *)malloc(sizeof(BiTNode));
  s-> data.key =key;  
  s->lchild=NULL;
  s->rchild=NULL;  
  b=s;
 }
 else if(key<b-> data.key) InsertBST(b->lchild,key); //将 s 插入左子树
 else if(key>b-> data.key) InsertBST(b->rchild,key); //将 s 插入右子树
}
4.二叉排序树删除操作
和插入相反,删除在查找成功之后进行,并且要求在删除二叉排序树上某个结点之后,仍然保持二叉排序树的特性。可分三种情况讨论:
(1)被删除的结点是叶子;
(2)被删除的结点只有左子树或者只有右子树;
(3)被删除的结点既有左子树,也有右子树。
int DeleteBST (BiTree &b, KeyType key ) {
 if (!p)    return FALSE; //不存在关键字等于 key 的数据元素
  else{
         if (EQ(key, b->data.key))     Delete (b); // 找到关键字等于 key 的数据元素
        else if (LT(key, b->data.key))   DeleteBST (b->lchild, key);
               else DeleteBST (b->rchild, key);
       return TRUE;
     }
}
其中删除操作过程如下描述:

void Delete ( BiTree &p ){
// 从二叉排序树中删除结点 p,并重接它的左或右子树
 if (!p->rchild) { // 右子树空则只需重接它的左子树
  q = p;
  p = p->lchild;
  free(q);
 }
 else if (!p->lchild) { // 只需重接它的右子树
  q = p;
  p = p->rchild;
  free(q);
 }
 else { // 左右子树均不空
  q = p;
  s = p->lchild;
  while (!s->rchild) { //转左,然后向右到尽头
   q = s;
   s = s->rchild;
      }
  p->data = s->data; // s 指向被删结点的前驱
  if (q != p )       q->rchild = s->lchild; // 重接*q 的右子树
  else q->lchild = s->lchild; // 重接*q 的左子树
  free(s);
  }
}

对给定序列建立二叉排序树,若左右子树均匀分布,则其查找过程类似于有序表的折半查找。但若给定序列原本有序,则建立的二叉排序树就蜕化为单链表,其查找效率同顺序查找一样。由值相同的 n 个关键字,构造所得的不同形态的各棵二叉排序树的平均查找长度的值不同,甚至可能差别很大。例如:

由关键字序列 1,2,3,4,5 构造而得的二叉排序树,ASL =(1+2+3+4+5)/ 5 = 3。
由关键字序列 3,1,2,5,4 构造而得的二叉排序树,ASL =(1+2+3+2+3)/ 5 = 2.2。
因此,对均匀的二叉排序树进行插入或删除结点后,应对其调整,使其依然保持均匀。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值