b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

数据结构与算法系列研究五——树、二叉树、三叉树、平衡排序二叉树AVL(4)

电脑杂谈  发布时间:2019-09-02 03:02:18  来源:网络整理

View Code

四、平衡排序二叉树AVL

4.1.实验内容

建立排序平衡二叉树。

4.2.输入与输出

输入:输入一组节点,从而构建平衡排序二叉树。

输出:输出平衡二叉树的先序,中序遍历,以及每个结点的平衡因子,以便进行还原二叉树的形状,判断算法能否恰当。

4.3.关键数据结构与核心算法

关键数据结构:

因为是二叉树,则要有基本的节点,左右孩子指针,因为要顺序转动,则要知道平衡因子,注意这里可以按照需要来添加双亲指针,因为采用了引用,则省去了这里。因此数据结构为:

typedef struct BSTNode

{

int data;//信息

int bf;//平衡因子

struct BSTNode *lchild,*rchild; //平衡树左右儿子指针

}BSTNode,*BSTree;//平衡二叉排序树结构的定义

核心算法:

建立平衡排序二叉树算是算法中非常复杂的一个了,但是找到核心以后,也就仅仅相当复杂一些罢了,多训练一下即可。那核心是哪个呢?要提问这个疑问,就要深刻理解“平衡”和“排序”两个词的涵义。顾名思义,平衡二叉树加上排序二叉树即是所要建的树。1.平衡二叉树要求每一个节点的左子树深度减去右子树的深度的绝对值要大于1。2.排序二叉树要求根据中序遍历该二叉树得到从小到大排序的序列。因此在每插入一个结点的之后都要判定是否平衡,1.若平衡则根据排序二叉树的方式插入之,然后刷新平衡因子即可。2.重要是不平衡的之后还要从最接近的不平衡的地方旋转的让它平衡,这样再次进去,不断插入就可以得到顺序平衡二叉树。

下面主要解释一下旋转技巧:旋转共有4种方式,其实二叉排序树 数据结构,最核心的唯有两种基本操作即是L_Rotate( )和R_Rotate( ),分别是左旋和右旋。

对于LL型,即是最先出错的节点平衡因子是2,左儿子平衡因子是1,运用一次右旋操作再刷新平衡因子即可。根据镜像对称方法,RR型与此是对应的,如法炮制即可。

重要的而且复杂的是LR和RL操作,这两个操作也有镜像对称的只讲一个即可。就包括LR吧,最先出错的节点的平衡因子是2,该节点的左孩子的平衡因子是-1.则要对左孩子为根的子树进行左旋,然后对该最近节点进行右旋,刷新平衡因子即可。具体算法如下:

技术分享技术分享

  1 /**************************两个基本操作*****************************/
  2 void L_Rotate(BSTree &p)  
  3 {
  4     //对以*p为根的二叉排序树做左旋处理,处理之后p指向新的树根结点
  5     //和R_Rotate()镜像对称
  6    BSTree rc;
  7    rc = p->rchild;
  8    p->rchild = rc->lchild;
  9    rc->lchild = p;
 10    p = rc;    
 11 }  
 12 void R_Rotate(BSTree &p)  
 13 {
 14     //对以*p为根的二叉排序树做右旋处理,处理之后p指向新的树根结点
 15     //注意此处引用的好处就是不用再出现双亲指针
 16    BSTree lc;
 17    lc=p->lchild; //指向B的位置
 18    p->lchild=lc->rchild; //此处转换仍保持中序遍历不变性
 19    lc->rchild=p; //更改a的指针位置
 20    p=lc;        //lc变成新的a
 21 }  
 22 /**********************四个旋转操作,每两个在一起*****************/
 23 //包含LL和LR
 24 void LeftBalance(BSTree &T)     
 25 {  //对已*T为根的二叉排序树做左平衡旋转处理
 26    BSTree lc,rd;
 27    lc = T->lchild; //lc调整左边
 28    switch(lc->bf)  
 29    {
 30      case LH://若是左边高则为LL型,只需旋转即可
 31          T->bf = lc->bf = EH; //旋转后平衡因子均为0
 32          R_Rotate(T); //LL型需要右旋转
 33          break;  
 34      case RH://若是右边高,则为LR型,需分两步调整
 35          rd = lc->rchild; //找到不确定因子rd
 36          switch(rd->bf)//对不确定因子进行讨论
 37          {
 38            case LH://左边高调整后
 39              T->bf = RH;//根节点右边变高
 40              lc->bf = EH; //lc变平衡
 41              break;
 42           case EH://rd有左右节点
 43             T->bf = lc->bf = EH; //调整后持平
 44             break;
 45           case RH://右边高
 46             T->bf = EH;//根节点平衡
 47             lc->bf = LH;//lc节点变成左边高
 48             break;  
 49          }  
 50         rd->bf=EH; //调整后rd节点一定平衡,且变成新的头节点
 51         L_Rotate(T->lchild); //1.先左旋
 52         R_Rotate(T);         //2.再右旋
 53    }
 54 }  
 55 /*************右平衡操作,包含RR和RL*******************************/
 56 void RightBalance(BSTree &T)  
 57 {
 58     //对已*T为根的二叉排序树做右平衡旋转处理
 59     //因为为LeftBalance(BSTree &T)的镜像,注释则省略
 60    BSTree lc,rd;
 61    lc = T->rchild;
 62    switch(lc->bf)
 63    {
 64     case RH://右边高,RR型
 65         T->bf = lc->bf = EH;
 66         L_Rotate(T);
 67         break;
 68     case LH://左边高,RL型,分两步旋转
 69        rd = lc->lchild;
 70        switch(rd->bf)
 71        {  
 72         case RH:
 73            T->bf = LH;
 74            lc->bf = EH;
 75            break;
 76         case LH:
 77            T->bf = EH;
 78            lc->bf = RH;
 79            break;
 80        case EH:
 81            T->bf = lc->bf = EH;
 82            break;
 83        }
 84        rd->bf = EH;
 85        R_Rotate(T->rchild); //1.先右旋
 86        L_Rotate(T);         //2.再左旋
 87    }
 88 }
 89     至于插入操作主要就是判断树是不是平衡,若不平衡是左边还是右边,对于添加的新节点改变了树的平衡了没有,改变了左边的还是右边的,然后进行相应的旋转处理。具体算法如下:
 90 int InsertAVL(BSTree &T, int key, bool &taller)  
 91 {
 92 //若在平衡二叉排序树中不存在与关键字key相等的结点,则将关键字插入树中
 93 //布尔变量taller表示树是否“长高”
 94   if(T==NULL)
 95   {
 96     T = (BSTree)malloc(sizeof(BSTNode));
 97     T->data = key;
 98     T->bf = EH;//叶子结点其平衡因子肯定为0
 99     T->lchild = T->rchild = NULL;
100     taller = 1;//树长高了
101   }
102   else
103   {
104      if(key==T->data)
105      {//如果树中已存放此关键字则不予插入
106        taller = 0;
107        return 0;
108      }
109      if(key<T->data)
110      {//关键字小于根结点则插入其左子树中
111           if(!InsertAVL(T->lchild,key,taller))
112                return 0;
113           if(taller)
114           {//如果树长高了,判断是否平衡
115             switch(T->bf)
116             {
117              case LH://若左边高,这次又加上一个左边的节点,则肯定变为2,即需要调整
118                  LeftBalance(T);//不平衡时调用左平衡函数,使左子树平衡
119                  taller = 0;
120                  break;
121              case EH://若相等,在左边加一个节点,则变为左边高
122                 T->bf = LH;
123                 taller = 1; //树变高
124                 break;
125              case RH://若右边高,在左边加一个节点,则持平
126                 T->bf = EH;
127                 taller = 0;
128                break;
129             }
130           }
131      }
132      else
133      {//插入右子树中
134         if(!InsertAVL(T->rchild,key,taller))
135           return 0;
136         if(taller)
137         {
138           switch(T->bf)
139           {
140             case LH://同理,本来左边高,在右边加一个节点则持平
141                 T->bf = EH;
142                 taller = 0;
143                 break;
144             case EH://右边变高
145                 T->bf = RH;
146                 taller = 1;
147                 break;
148             case RH://右边不平衡了,需要调整
149                 RightBalance(T);
150                 taller = 0;
151                 break;
152           }
153         }
154      }
155   }
156         return 1;
157 }  


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-121392-4.html

相关阅读
    发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

    • 赵成侯
      赵成侯

      舰载武器质量和威力也很重要

    • 田杰
      田杰

      打完了把它拖到12海里以内来

    • 翟长彪
      翟长彪

      中国须严阵以待

    热点图片
    拼命载入中...