查找(2)--动态查找

动态查找表:1.表结构本身是在查找过程中动态生成的,即对于给定值 key ,若表中存在关键字等于 key 的记录,则查找成功返回;否则,插入关键字等于 key 的记录。

                        2.动态查找表主要有二叉树结构和树结构两种类型。二叉树结构有二叉排序树、平衡二叉树等。树结构有B-树、B+树等。


一.二叉排序树:

         1.定义:

               1)若它的左子树不空,则左子树上所有结点的值均小于根结点的值; 
               2)若它的右子树不空,则右子树上所有结点的值均大于根结点的值; 
               3)它的左、右子树也都分别是二叉排序树。 

                

         2.存储结构:         

struct  BtreeNode { 
   ElemType  key;  //关键字
   BtreeNode *lchild, *rchild;//左、右孩子
} BtreeNode,  *Bitree;
        3.相关操作:

               (1)查找:                                  

BiTree SearchBST(BiTree T, KeyType key)

{  
    //若查找成功,则返回指向该数据元素结点的指针
  
    //否则返回空指针。  
    if ( (!T) || key = T-> data.key  ) return(T);
    else 
         if ( key < T-> data.key) 
                   return(SearchBST (T-> lchild, key)); //在左子树中继续查找
   
         else 
        
                   return(SearchBST (T-> rchild, key)); //在右子树中继续查找

} // SearchBST
               (2)插入:

                         1) 若二叉排序树为空树,则新插入的结点为根结点; 
                         2) 若二叉排序树非空,则新插入的结点必为一个新的叶子结点,并且是查找不成功时查找路径上访问的最后一个结点的左孩子或右孩子结点。                

Status SearchBST (BiTree T, KeyType key, BiTree f, BiTree &p )  

{  //若查找成功,则指针 p 指向该数据元素结点,并返回 TRUE
    
   //否则指针 p 指向查找路径上访问的最后一个结点,并返回 FALSE
   
   //指针 f 指向 T 的双亲,其初始调用值为NULL。 
   if (!T) { p = f; return FALSE; }  // 查找不成功
   else 
       if ( key = T-> data.key ) { p = T;  return TRUE; }  // 查找成功 
       else
           if ( key < T-> data.key )
                   
                SearchBST (T -> lchild, key, T, p ); // 在左子树中查找 
          
           else 
                SearchBST (T-> rchild, key, T, p ); // 在右子树中查找 
} // SearchBST 

Status InsertBST(BiTree &T, ElemType e )
{   
   // 当二叉排序树 T 中不存在关键字等于 e.key 的数据元素时, 
    
   // 插入 e 并返回 TRUE,否则返回 FALSE
   if (!SearchBST ( T, e.key,NULL,p)) 
     {  // 查找不成功 
         s = (BiTree) malloc (sizeof (BiTNode));
         s -> data = e;  s -> lchild = s -> rchild = NULL; 
         if ( !p )   T = s;   // 插入 s 为新的根结点
         else 
              if ( e.key < p -> data.key )  p -> lchild = s;  // 插入 s 为左孩子 
              else  p -> rchild = s;    // 插入 s 为右孩子 
         return TRUE;
      }  
   else 
       return FALSE;   // 树中已有关键字相同的结点,不再插入 
} // Insert BST 
                (3)建立二叉排序树:             

//反复调用二叉排序树的插入算法即可
Bitree   Creat (int  n) {
    //建立含有n个结点的二叉排序树
    Bitree T= NULL;
    for ( int i=1; i<=n; i++) 
{
         cin>>x;    //输入关键字序列
         InsertBST ( T, x); 
}   
    return   BST;
}
                 (4)删除结点,删除后二叉排序树中序遍历依然有序(三种情况):

                               1)若*p结点为叶子结点,即PL和PR均为空树。
                                         由于删去叶子结点不破坏整棵树的结构,则只需修改其双亲结点的指针。 

                               2)P只有左子树或右子树:
                                        P只有左(右)子树,用P的左(右)孩子代替P; 。

                               3)P左、右子树均非空
                                       用P的直接前驱(或直接后继)取代P

            

4.二叉排序树的查找分析

       (1)含有 n 个结点的二叉排序树的平均查找长度和树的形态有关               

                例如:

                                   

                                                                                                                               图(1)

                              

                                                                                                                                        图(2)

                                     最好情况: ASL= – 1,  树的深度为└ log2n ┘ + 1(向下取整) ,与折半查找中的判定树相同(形态比较均衡);

                                     最坏情况:插入的 n 个元素从一开始就有序, 变成单支树的形态! 此时树的深度为 n;   
                                                          A SL = (n + 1) / 2   ,查找效率与顺序查找情况相同。 

                               很明显不同的二叉排序树的ASL与形态有关!!!

                                实验证明,二叉树形态越均衡,ASL越短,那么如何提高形态不均衡的二叉排序树的查找效率?引入平衡二叉树。

      

二.平衡二叉树(AVL树)

              1.概念:|左子树深度-右子树深度| ≤ 1

                         

                               其中-1,0,1为平衡因子,显然AVL树只能有这三个平衡因子!


             2.平衡二叉树的调整

                            (1).LL平衡旋转:若在 A 的左子树的左子树上插入 
                                                  结点,使 A 的平衡因子从 1 增加 
                                                  至 2, 需要进行一次顺时针旋转。  (以 B 为旋转轴) 

                                   

                            (2).RR 平衡旋转:若在 A 的右子树的右子树上插入 
                                                           结点,使 A 的平衡因子从 -1 改变
                                                            为 -2,需要进行一次逆时针旋转。 (以 B 为旋转轴)          

                                                                               

                            (3) .LR平衡旋转:若在 A 的左子树的右子树上插入 
                                                            结点,使 A 的平衡因子从 1 增加 
                                                            至 2, 需要先进行逆时针旋转,  
                                                             再顺时针旋转。 (以插入的结点 B 为旋转轴)

                                   

                            (4).RL平衡旋转:

                                                        若在 A 的右子树的左子树上插入 
                                                        结点,使 A 的平衡因子从 -1 改变 
                                                       为 -2,需要先进行顺时针旋转,再逆时针旋转。(以插入的结点 B 为旋转轴)

                                   

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值