zoukankan      html  css  js  c++  java
  • 数据结构学习笔记04树(二叉树、二叉搜索树、平衡二叉树)

    一.树

    树的基本术语

      ①结点的度(Degree):结点的子树个数

      ②树的度:树的所有结点中最大的度数

      ③叶结点(Leaf):度为0的结点

      ④父结点(Parent):有子树的结点是其子树的根结点的父结点

      ⑤子结点(Child):若A结点是B结点的父结点,则称B结点是A结点的子结点;子结点也称孩子结点。

      ⑥兄弟结点(Sibling):具有同一父结点的各结点彼此是兄弟结点。

      ⑦路径和路径长度:从结点n1到nk的路径为一个结点序列n1 , n2 ,… , nk , ni是 ni+1的父结点。路径所包含边的个数为路径的长度。

      ⑧ 祖先结点(Ancestor):沿树根到某一结点路径上的所有结点都是这个结点的祖先结点。

      ⑨子孙结点(Descendant):某一结点的子树中的所有结点是这个结点的子孙。

        ⑩结点的层次(Level):规定根结点在1层,其它任一结点的层数是其父结点的层数加1。 12. 树的深度(Depth):树中所有结点中的最大层次是这棵树的深度。

    二.二叉树

    二叉树的性质

      ①一个二叉树第 i 层的最大结点数为:2^(i-1) (i>=1)

      ②深度为k的二叉树至多有2^k-1个结点 (i>=1)

      ③对任何非空二叉树 T,若n0表示叶结点的个数、n2是度为2的非叶结点个数,那么两者满足关系n0 = n2 +1    ---> n0+n1+n2 = B + 1 = n0 * 0 + n1 * 1 + n2 * 2 + 1

    1.顺序存储结构

    完全二叉树:按从上至下、从左到右顺序存储

    N个结点的完全二叉树的结点父子关系:

      ①    非根结点(序号i > 1)的父结点的序号[ i / 2]

      ②    结点(序号为i) 的左孩子结点序号 2i,(若2i <=n,否则无左孩子)

      ③    结点(序号为i) 的左孩子结点序号 2i +1,(若2i + 1<=n,否则无右孩子)

    非完全二叉树 ---> 补全为完全二叉树

    2.链式存储结构(代码:sj4_0)

      1 //二叉树
      2 #include <iostream>
      3 #include <cstdio>
      4 #include <stdlib.h>
      5 #include <stack>
      6 #include <queue>
      7 using namespace std;
      8 #define OK 1
      9 #define ERROR 0
     10 #define OVERFLOW -1
     11 
     12 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
     13 typedef int TElemType;/* ElemType类型根据实际情况而定,这里假设为int*/
     14 
     15 typedef struct BinTNode *BinTree;
     16 struct BinTNode
     17 {
     18     TElemType data;
     19     BinTree left;
     20     BinTree right;
     21 }; 
     22 
     23 Status CreatBiTree(BinTree &T);
     24 Status PreOrderTraverse(BinTree T);
     25 Status InOderTraverse(BinTree T);
     26 Status PostOrderTraverse(BinTree T);
     27 
     28 Status StackPreOrderTraverse(BinTree T);
     29 Status StackInOrderTraverse(BinTree T);
     30 Status StackPostOrderTraverse(BinTree T);
     31 
     32 Status LevelOrderTraverse(BinTree T);
     33 
     34 int PostOrderGetHeight(BinTree T);
     35 
     36 Status InitBiTree(BinTree &T);
     37 Status DestroyBiTree(BinTree &T);
     38 Status ClearBiTree(BinTree &T);
     39 bool BiTreeEmpty(BinTree T);
     40 TElemType Root(BinTree T);
     41 TElemType Value(BinTree p);
     42 void Assign(BinTree p,TElemType value);
     43  
     44 /*按先序次序输入二叉树中的结点值,负数表示空树 
     45 构造二叉链表表示的二叉树*/
     46 Status CreatBiTree(BinTree &T)        
     47 {
     48     TElemType data;
     49     scanf("%d",&data);
     50     if(data < 0 ) 
     51         T = NULL;
     52     else {
     53         if( !(T = (BinTree)malloc(sizeof(BinTNode))) )
     54             exit(OVERFLOW); 
     55         T->data = data;
     56         CreatBiTree(T->left);
     57         CreatBiTree(T->right);
     58     }
     59     return OK;
     60 }
     61 
     62 //递归实现先序遍历 
     63 Status PreOrderTraverse(BinTree T)
     64 {
     65     if(T) {
     66         printf("%5d", T->data);
     67         PreOrderTraverse(T->left);
     68         PreOrderTraverse(T->right);
     69     }
     70     return OK;
     71 }
     72 //递归实现中序遍历 
     73 Status InOderTraverse(BinTree T)
     74 {
     75     if(T) {
     76         PreOrderTraverse(T->left);
     77         printf("%5d", T->data);
     78         PreOrderTraverse(T->right);
     79     }
     80     return OK;
     81 }
     82 //递归实现后序遍历  
     83 Status PostOrderTraverse(BinTree T)
     84 {
     85     if(T) {
     86         PreOrderTraverse(T->left);
     87         PreOrderTraverse(T->right);
     88         printf("%5d", T->data);
     89     }
     90     return OK;
     91 }
     92 
     93 //非递归实现先序遍历:堆栈 
     94 Status StackPreOrderTraverse(BinTree T)
     95 {
     96     if(T == NULL)
     97         return ERROR;  
     98     BinTree BT = T;
     99     stack<BinTree> stack;
    100     while(BT || !stack.empty() ) {
    101         while(BT) {            //一直向左将沿途结点压入堆栈 
    102             printf("%5d",BT->data);    //访问打印结点 
    103             stack.push(BT);
    104             BT = BT->left;
    105         }
    106         if( !stack.empty() ) {    
    107             BT = stack.top();        //记录弹出结点 
    108             stack.pop();
    109             BT = BT->right;         //转向右子树 
    110         }
    111     }
    112     return OK;    
    113 }
    114 
    115 //非递归实现中序遍历:堆栈 
    116 Status StackInOrderTraverse(BinTree T)
    117 {
    118     if(T == NULL)
    119         return ERROR;  
    120     BinTree BT = T;
    121     stack<BinTree> stack;
    122     while(BT || !stack.empty() ) {
    123         while(BT) {            //一直向左将沿途结点压入堆栈 
    124             stack.push(BT);
    125             BT = BT->left;
    126         }
    127         if( !stack.empty() ) {        //////
    128             BT = stack.top();        //记录弹出结点 
    129             stack.pop();
    130             printf("%5d",BT->data);    //访问打印结点 
    131             BT = BT->right;         //转向右子树 
    132         }
    133     }
    134     return OK;    
    135 }
    136 
    137 //非递归实现后序遍历:堆栈 
    138 /*后序遍历LRG:第一遍入栈,G再第二遍被遍历到时,若有右孩子,则入栈(等待第三次遍历);
    139 如无右孩子,或右孩子已被访问,则访问G结点。*/ 
    140 Status StackPostOrderTraverse(BinTree T)
    141 {
    142     if(T == NULL)
    143         return ERROR;  
    144     BinTree BT = T;
    145     stack<BinTree> stack;
    146     BinTree lastNode = NULL, currentNode = NULL;//lastNode记录被访问过的前一个结点 
    147     while( BT || !stack.empty() ) {
    148         while(BT) {                //一直向左将沿途结点压入堆栈 
    149             stack.push(BT);
    150             BT = BT->left;
    151         }
    152         while( !stack.empty() ) {
    153             currentNode = stack.top();    //当前节点
    154             stack.pop();                //出栈
    155             if( currentNode->right == NULL || currentNode->right == lastNode) {//无右子树或右子树已被访问     
    156                 printf("%5d",currentNode->data);
    157                 lastNode = currentNode;
    158             }else {        //右子树未被访问过 
    159                 stack.push(currentNode);
    160                 currentNode = currentNode->right;
    161                 while(currentNode) {
    162                     stack.push(currentNode);
    163                     currentNode = currentNode->left;
    164                 }
    165             }
    166         }
    167     }
    168     return OK;
    169 }
    170 
    171 //层序遍历:队列 
    172 Status LevelOrderTraverse(BinTree T)
    173 {
    174     if(T == NULL)
    175         return ERROR;
    176     BinTree BT = T;
    177     queue<BinTree> queue;
    178     queue.push(BT);
    179     while( !queue.empty() ) {
    180         BinTree temp = queue.front();
    181         printf("%5d", temp->data);
    182         queue.pop();
    183         if(temp->left)
    184             queue.push(temp->left);
    185         if(temp->right)
    186             queue.push(temp->right);
    187     }
    188     printf("
    ");
    189     return OK;
    190 }
    191 
    192 //后序遍历求树深度(高) 
    193 int PostOrderGetHeight(BinTree T)
    194 {
    195     int leftHeight, rightHeight, maxHeight;
    196     if(T) {
    197         leftHeight = PostOrderGetHeight(T->left);    //左子树深度 
    198         rightHeight = PostOrderGetHeight(T->right);    //右子树深度 
    199         maxHeight = leftHeight > rightHeight ? leftHeight : rightHeight;
    200         return (maxHeight+1);    //返回树的深度 
    201     }
    202     else 
    203         return 0;//空树深度为0 
    204 } 
    205  
    206 //构造空二叉树T 
    207 Status InitBiTree(BinTree &T)
    208 {
    209     T = NULL;
    210     return OK;
    211 }
    212 //销毁二叉树T 
    213 Status DestroyBiTree(BinTree &T)
    214 {
    215     if(T) {
    216         if(T->left)
    217             DestroyBiTree(T->left);
    218         if(T->right)
    219             DestroyBiTree(T->right);
    220         free(T);    //释放该结点 
    221         T = NULL;    //T置空 
    222     }
    223     return OK;
    224 }
    225 /*清空二叉树T 
    226 清空和销毁有什么区别么*/ 
    227 Status ClearBiTree(BinTree &T)
    228 {
    229     if(T) {
    230         if(T->left)
    231             DestroyBiTree(T->left);
    232         if(T->right)
    233             DestroyBiTree(T->right);
    234         free(T);    //释放该结点 
    235         T = NULL;    //T置空 
    236     }
    237     return OK;
    238 } 
    239 
    240 bool BiTreeEmpty(BinTree T)
    241 {
    242     if( !T )
    243         return true;
    244     else
    245         return false;
    246 }
    247 
    248 //返回T的根
    249 TElemType Root(BinTree T)
    250 { 
    251     if(BiTreeEmpty(T))
    252         return -1;
    253     else
    254         return T->data;
    255 }
    256 
    257 //返回p所指结点的值 
    258 TElemType Value(BinTree p)
    259 {
    260     return p->data;
    261 }
    262 
    263 // 给p所指结点赋值为value 
    264 void Assign(BinTree p,TElemType value)
    265 {
    266     p->data=value;
    267 }
    268 
    269 
    270 
    271 int main()
    272 {
    273     BinTree T;
    274     CreatBiTree(T);
    275     printf("先序递归遍历:  "); 
    276     PreOrderTraverse(T);
    277     printf("
    先序非递归遍历:"); 
    278     StackPreOrderTraverse(T);
    279     
    280     printf("
    中序递归遍历:  "); 
    281     InOderTraverse(T);
    282     printf("
    中序非递归遍历:"); 
    283     StackInOrderTraverse(T);
    284     
    285     printf("
    后序递归遍历:  "); 
    286     PostOrderTraverse(T);
    287     printf("
    后序非递归遍历:"); 
    288     StackPostOrderTraverse(T);
    289     
    290     printf("
    层序遍历:      "); 
    291     LevelOrderTraverse(T);
    292     printf("
    树的高度:%d
    ",PostOrderGetHeight(T)); 
    293     if(BiTreeEmpty(T))
    294         printf("");
    295     else
    296         printf("不空
    ");
    297     printf("树的根:%d
    ",Root(T)); 
    298     
    299         
    300 
    301     return 0;
    302 }
    sj4_0

    先序GLR:第一次遇到该结点则输出。

    中序LGR:第二次遇到该结点则输出。

    后序LRG:第三次遇到该结点则输出。

    typedef struct BinTNode *BinTree;

    struct BinTNode

    {

           TElemType data;

           BinTree left;

           BinTree right;

    };

    先序递归算法

     1 //递归实现先序遍历 
     2 Status PreOrderTraverse(BinTree T)
     3 {
     4     if(T) {
     5         printf("%5d", T->data);
     6         PreOrderTraverse(T->left);
     7         PreOrderTraverse(T->right);
     8     }
     9     return OK;
    10 }
    View Code

    先序遍历非递归遍历算法

      ①遇到一个结点,访问打印它,将其压栈,并遍历它的左子树

      ②当左子树遍历结束后,从栈顶弹出这个结点

      ③然后按其右指针再去先序遍历该结点的右子树

     1 Status StackPreOrderTraverse(BinTree T)
     2 {
     3     if(T == NULL)
     4         return ERROR;  
     5     BinTree BT = T;
     6     stack<BinTree> stack;
     7     while(BT || !stack.empty() ) {
     8         while(BT) {            //一直向左将沿途结点压入堆栈 
     9             printf("%5d",BT->data);    //访问打印结点 
    10             stack.push(BT);
    11             BT = BT->left;
    12         }
    13         if( !stack.empty() ) {    
    14             BT = stack.top();        //记录弹出结点 
    15             stack.pop();
    16             BT = BT->right;         //转向右子树 
    17         }
    18     }
    19     return OK;    
    20 }
    View Code

    中序遍历非递归遍历算法

      ①遇到一个结点,就把它压栈,并遍历它的左子树

      ②当左子树遍历结束后,从栈顶弹出这个结点并访问它

      ③然后按其右指针再去中序遍历该结点的右子树

     1 //非递归实现中序遍历:堆栈 
     2 Status StackInOrderTraverse(BinTree T)
     3 {
     4     if(T == NULL)
     5         return ERROR;  
     6     BinTree BT = T;
     7     stack<BinTree> stack;
     8     while(BT || !stack.empty() ) {
     9         while(BT) {            //一直向左将沿途结点压入堆栈 
    10             stack.push(BT);
    11             BT = BT->left;
    12         }
    13         if( !stack.empty() ) {        //////
    14             BT = stack.top();        //记录弹出结点 
    15             stack.pop();
    16             printf("%5d",BT->data);    //访问打印结点 
    17             BT = BT->right;         //转向右子树 
    18         }
    19     }
    20     return OK;    
    21 }
    View Code

    后序遍历非递归算法

      后序遍历LRG:第一遍入栈,G再第二遍被遍历到时,若有右孩子,则入栈(等待第三次遍历);如无右孩子,或右孩子已被访问,则访问G结点。

     1 //非递归实现后序遍历:堆栈 
     2 Status StackPostOrderTraverse(BinTree T)
     3 {
     4     if(T == NULL)
     5         return ERROR;  
     6     BinTree BT = T;
     7     stack<BinTree> stack;
     8     BinTree lastNode = NULL, currentNode = NULL;//lastNode记录被访问过的前一个结点 
     9     while( BT || !stack.empty() ) {
    10         while(BT) {                //一直向左将沿途结点压入堆栈 
    11             stack.push(BT);
    12             BT = BT->left;
    13         }
    14         while( !stack.empty() ) {
    15             currentNode = stack.top();    //当前节点
    16             stack.pop();                //出栈
    17             if( currentNode->right == NULL || currentNode->right == lastNode) {//无右子树或右子树已被访问     
    18                 printf("%5d",currentNode->data);
    19                 lastNode = currentNode;
    20             }else {        //右子树未被访问过 
    21                 stack.push(currentNode);
    22                 currentNode = currentNode->right;
    23                 while(currentNode) {
    24                     stack.push(currentNode);
    25                     currentNode = currentNode->left;
    26                 }
    27             }
    28         }
    29     }
    30     return OK;
    31 }
    View Code

    层序遍历算法:先根结点入队,然后

      ①从队列取出一个元素

      ②访问打印该元素所指结点

      ③若该元素有左右孩子,则左右孩子顺序入队

     1 //层序遍历:队列 
     2 Status LevelOrderTraverse(BinTree T)
     3 {
     4     if(T == NULL)
     5         return ERROR;
     6     BinTree BT = T;
     7     queue<BinTree> queue;
     8     queue.push(BT);
     9     while( !queue.empty() ) {
    10         BinTree temp = queue.front();
    11         printf("%5d", temp->data);
    12         queue.pop();
    13         if(temp->left)
    14             queue.push(temp->left);
    15         if(temp->right)
    16             queue.push(temp->right);
    17     }
    18     printf("
    ");
    19     return OK;
    20 }
    View Code

    三.二叉搜索树(二叉排序树 二叉查找树)(代码:sj4_1)

     1 //二叉搜索树(BST) 
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 
     5 #define OK 1
     6 #define ERROR 0
     7 #define OVERFLOW -1 
     8 
     9 typedef int Status;/* Status是函数的类型,其值是函数结果状态代码,如OK等 */
    10 typedef int TElemType;/* ElemType类型根据实际情况而定,这里假设为int*/
    11 
    12 
    13 typedef struct BinTNode *BSTree;
    14 struct BinTNode
    15 {
    16     TElemType data;
    17     BSTree left;
    18     BSTree right;
    19 }; 
    20 //查找X,若成功返回结点地址,失败返回NULL 
    21 BSTree Find(TElemType X,BSTree BST)
    22 {
    23     while(BST) {
    24         if(X < BST->data) 
    25             BST = BST->left;
    26         else if(X > BST->data)
    27             BST = BST->right;
    28         else
    29             return BST;
    30     }
    31     return NULL;
    32 }
    33 //从二叉搜索树BST中查找并返回最小元素所在结点的地址 
    34 BSTree FindMin(BSTree BST)
    35 {
    36     if(BST)
    37         while(BST->left) 
    38             BST = BST->left;
    39     return BST;    
    40 }
    41 
    42 //从二叉搜索树BST中查找并返回最大元素所在结点的地址
    43 BSTree FindMax(BSTree BST)
    44 {
    45     if(BST)
    46         while(BST->right) 
    47             BST = BST->right;
    48     return BST;
    49 }
    50  
    51 //插入结点X 
    52 BSTree Insert(TElemType X,BSTree BST)
    53 {
    54     if(!BST) {            //空则建结点 
    55         BST = (BSTree)malloc(sizeof(struct BinTNode));
    56         BST->data = X;
    57         BST->left = BST->right = NULL;
    58     }else {
    59         if(X > BST->data)        //X大于该结点,递归插入右子树 
    60             Insert(X,BST->right);
    61         else if(X < BST->data)    //X小于该结点,递归插入做子树 
    62             Insert(X,BST->left);
    63         //相等,已存在,什么都不做 
    64     }
    65     return BST;
    66 }
    67 
    68 //删除结点X 
    69 BSTree Delete(TElemType X,BSTree BST)
    70 {
    71     if(!BST) {
    72         printf("未找到要删除的结点
    "); 
    73         return ERROR;
    74     }
    75     if(X > BST->data) 
    76         BST->right = Delete(X,BST->right);
    77     else if(X < BST->data)
    78         BST->left = Delete(X,BST->left);
    79     else {    //找到要删除的结点 
    80         if(BST->left && BST->right) {        //要删除结点有左右两个孩子 
    81             BSTree Temp = FindMin(BST);    //在右子树中找到最小元素填充要删除元素 
    82             BST->data = Temp->data;
    83             BST->right = Delete(Temp->data,BST->right);//删除最小元素 
    84         }else {                        //要删除结点只有一个孩子或没有孩子 
    85             BSTree Temp = BST; 
    86             if(!BST->left)            //如果左孩子空
    87                 BST = BST->right;
    88             if(!BST->right)            //如果右孩子空
    89                 BST = BST->left;
    90             free(Temp); 
    91         }
    92     }
    93     return BST;
    94 } 
    sj4_1

    二叉搜索树:一棵二叉树,可以为空;如果不为空,满足以下性质:

      ①非空左子树的所有键值小于其根结点的键值。

      ② 非空右子树的所有键值大于其根结点的键值。

      ③ 左、右子树都是二叉搜索树。

    BSTree Find(TElemType X,BSTree BST):从二叉搜索树BST中查找元素X,返回其所在结点的地址;

    BSTree FindMin(BSTree BST)从二叉搜索树BST中查找并返回最小元素所在结点的地址;

    BSTree FindMax(BSTree BST):从二叉搜索树BST中查找并返回最大元素所在结点的地址。

    BSTree Insert(TElemType X,BSTree BST)

    BSTree Delete(TElemType X,BSTree BST)

    1.二叉搜索树的查找

    算法思路:查找从根结点开始,如果树为空,返回NULL

      若搜索树非空,则根结点关键字和X进行比较,并进行不同处理:

      若X小于根结点键值,只需在左子树中继续搜索;

      如果X大于根结点的键值,在右子树中进行继续搜索;

      若两者比较结果是相等,搜索完成,返回指向此结点的指针。

    最大元素一定是在树的最右分枝的端结点上

    最小元素一定是在树的最左分枝的端结点上

     1 //查找X,若成功返回结点地址,失败返回NULL 
     2 BSTree Find(TElemType X,BSTree BST)
     3 {
     4     while(BST) {
     5         if(X < BST->data) 
     6             BST = BST->left;
     7         else if(X > BST->data)
     8             BST = BST->right;
     9         else
    10             return BST;
    11     }
    12     return NULL;
    13 }
    14 //从二叉搜索树BST中查找并返回最小元素所在结点的地址 
    15 BSTree FindMin(BSTree BST)
    16 {
    17     if(BST)
    18         while(BST->left) 
    19             BST = BST->left;
    20     return BST;    
    21 }
    22 
    23 //从二叉搜索树BST中查找并返回最大元素所在结点的地址
    24 BSTree FindMax(BSTree BST)
    25 {
    26     if(BST)
    27         while(BST->right) 
    28             BST = BST->right;
    29     return BST;
    30 }
    View Code

    2.二叉搜索树的删除

      三种情况:

        ①要删除的是叶结点:直接删除,并再修改其父结点指针---置为NULL

        ②要删除的结点只有一个孩子结点: 将其父结点的指针指向要删除结点的孩子结点

        ③要删除的结点有左、右两棵子树: 用另一结点替代被删除结点:右子树的最小元素 或者 左子树的最大元素

     1 //删除结点X 
     2 BSTree Delete(TElemType X,BSTree BST)
     3 {
     4     if(!BST) {
     5         printf("未找到要删除的结点
    "); 
     6         return ERROR;
     7     }
     8     if(X > BST->data) 
     9         BST->right = Delete(X,BST->right);
    10     else if(X < BST->data)
    11         BST->left = Delete(X,BST->left);
    12     else {    //找到要删除的结点 
    13         if(BST->left && BST->right) {        //要删除结点有左右两个孩子 
    14             BSTree Temp = FindMin(BST);    //在右子树中找到最小元素填充要删除元素 
    15             BST->data = Temp->data;
    16             BST->right = Delete(Temp->data,BST->right);//删除最小元素 
    17         }else {                        //要删除结点只有一个孩子或没有孩子 
    18             BSTree Temp = BST; 
    19             if(!BST->left)            //如果左孩子空
    20                 BST = BST->right;
    21             if(!BST->right)            //如果右孩子空
    22                 BST = BST->left;
    23             free(Temp); 
    24         }
    25     }
    26     return BST;
    27 } 
    View Code

    四.平衡二叉树(Balanced Binary Tree)(AVL树)(代码:sj4_2)

      1 //平衡二叉树 AVL 
      2 #include <stdio.h>
      3 #include <stdlib.h>
      4 
      5 typedef int ElementType;
      6 
      7 typedef struct AVLNode *Position;
      8 typedef Position AVLTree; /* AVL树类型 */
      9 typedef struct AVLNode{
     10     ElementType data; /* 结点数据 */
     11     AVLTree left;     /* 指向左子树 */
     12     AVLTree right;    /* 指向右子树 */
     13     int height;       /* 树高 */
     14 };
     15  
     16 int Max ( int a, int b )
     17 {
     18     return a > b ? a : b;
     19 }
     20 
     21 int GetHeight( Position p )
     22 {
     23     if(!p)
     24         return -1;
     25     return p->height;
     26 }
     27 
     28 /* 将A与B做左单旋,更新A与B的高度,返回新的根结点B */ 
     29 /* 注意:A必须有一个左子结点B */    
     30 AVLTree SingleLeftRotation ( AVLTree A )
     31 {
     32     AVLTree B = A->left;
     33     A->left = B->right;
     34     B->right = A;
     35     A->height = Max( GetHeight(A->left), GetHeight(A->right) ) + 1;
     36     B->height = Max( GetHeight(B->left), A->height ) + 1;
     37   
     38     return B;
     39 }
     40 /* 将A与B做右单旋,更新A与B的高度,返回新的根结点B */ 
     41 /* 注意:A必须有一个右子结点B */
     42 AVLTree SingleRightRotation ( AVLTree A )
     43 { 
     44     AVLTree B = A->right;
     45     A->right = B->left;
     46     B->left = A;
     47     A->height = Max( GetHeight(A->left), GetHeight(A->right) ) + 1;
     48     B->height = Max( A->height, GetHeight(B->right) ) + 1;
     49   
     50     return B;
     51 }
     52 
     53 /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */
     54 /* 将A、B与C做两次单旋,返回新的根结点C */ 
     55 AVLTree DoubleLeftRightRotation ( AVLTree A )
     56 { 
     57     /* 将B与C做右单旋,C被返回 */
     58     A->left = SingleRightRotation(A->left);
     59     /* 将A与C做左单旋,C被返回 */
     60     return SingleLeftRotation(A);
     61 }
     62 
     63 /* 将A、B与C做两次单旋,返回新的根结点C */ 
     64 /* 注意:A必须有一个右子结点B,且B必须有一个左子结点C */
     65 AVLTree DoubleRightLeftRotation ( AVLTree A )
     66 { 
     67     /* 将B与C做右单旋,C被返回 */
     68     A->right = SingleLeftRotation(A->right);
     69     /* 将A与C做左单旋,C被返回 */
     70     return SingleRightRotation(A);
     71 }
     72 
     73 /* 将X插入AVL树T中,并且返回调整后的AVL树 */
     74 AVLTree Insert( AVLTree T, ElementType X )
     75 { 
     76     if ( !T ) { /* 若插入空树,则新建包含一个结点的树 */
     77         T = (AVLTree)malloc(sizeof(struct AVLNode));
     78         T->data = X;
     79         T->height = 0;
     80         T->left = T->right = NULL;
     81     } /* if (插入空树) 结束 */
     82  
     83     else if ( X < T->data ) {
     84         T->left = Insert( T->left, X);/* 插入T的左子树 */
     85         if ( GetHeight(T->left)-GetHeight(T->right) == 2 ) /* 如果需要左旋 */
     86             if ( X < T->left->data ) 
     87                T = SingleLeftRotation(T);      //左单旋 LL
     88             else 
     89                T = DoubleLeftRightRotation(T); //左-右双旋LR
     90     } /* else if (插入左子树) 结束 */
     91      
     92     else if ( X > T->data ) {
     93         T->right = Insert( T->right, X );/* 插入T的右子树 */
     94         if ( GetHeight(T->left)-GetHeight(T->right) == -2 )/* 如果需要右旋 */
     95             if ( X > T->right->data ) 
     96                T = SingleRightRotation(T);     //右单旋 RR
     97             else 
     98                T = DoubleRightLeftRotation(T); //右-左双旋 RL
     99     } /* else if (插入右子树) 结束 */
    100  
    101     /*else X == T->Data,无须插入 */
    102     T->height = Max( GetHeight(T->left), GetHeight(T->right) ) + 1;    //更新树高 
    103      
    104     return T;
    105 }
    106 
    107 int main()
    108 {
    109     int N, data;
    110     AVLTree T;
    111     scanf("%d",&N);
    112     for(int i = 0; i < N; i++) {
    113         scanf("%d",&data);
    114         T = Insert(T,data);
    115     }
    116     printf("%d
    ",T->data);
    117     return 0;
    118 }
    sj4_2

    平衡因子(Balance Factor,简称BF): BF(T) = hL-hR,

    平衡二叉树:空树,或者 任一结点左、右子树高度差的绝对值不超过1,即|BF(T) |≤ 1

    1.LL

     1 /* 将A与B做左单旋,更新A与B的高度,返回新的根结点B */ 
     2 /* 注意:A必须有一个左子结点B */    
     3 AVLTree SingleLeftRotation ( AVLTree A )
     4 {
     5     AVLTree B = A->left;
     6     A->left = B->right;
     7     B->right = A;
     8     A->height = Max( GetHeight(A->left), GetHeight(A->right) ) + 1;
     9     B->height = Max( GetHeight(B->left), A->height ) + 1;
    10   
    11     return B;
    12 }
    View Code

    2.RR

     1 /* 将A与B做右单旋,更新A与B的高度,返回新的根结点B */ 
     2 /* 注意:A必须有一个右子结点B */
     3 AVLTree SingleRightRotation ( AVLTree A )
     4 { 
     5     AVLTree B = A->right;
     6     A->right = B->left;
     7     B->left = A;
     8     A->height = Max( GetHeight(A->left), GetHeight(A->right) ) + 1;
     9     B->height = Max( A->height, GetHeight(B->right) ) + 1;
    10   
    11     return B;
    12 }
    View Code

    3.LR

    1 /* 注意:A必须有一个左子结点B,且B必须有一个右子结点C */
    2 /* 将A、B与C做两次单旋,返回新的根结点C */ 
    3 AVLTree DoubleLeftRightRotation ( AVLTree A )
    4 { 
    5     /* 将B与C做右单旋,C被返回 */
    6     A->left = SingleRightRotation(A->left);
    7     /* 将A与C做左单旋,C被返回 */
    8     return SingleLeftRotation(A);
    9 }
    View Code

    4.RL

    1 /* 将A、B与C做两次单旋,返回新的根结点C */ 
    2 /* 注意:A必须有一个右子结点B,且B必须有一个左子结点C */
    3 AVLTree DoubleRightLeftRotation ( AVLTree A )
    4 { 
    5     /* 将B与C做右单旋,C被返回 */
    6     A->right = SingleLeftRotation(A->right);
    7     /* 将A与C做左单旋,C被返回 */
    8     return SingleRightRotation(A);
    9 }
    View Code

    5.insert

     1 /* 将X插入AVL树T中,并且返回调整后的AVL树 */
     2 AVLTree Insert( AVLTree T, ElementType X )
     3 { 
     4     if ( !T ) { /* 若插入空树,则新建包含一个结点的树 */
     5         T = (AVLTree)malloc(sizeof(struct AVLNode));
     6         T->data = X;
     7         T->height = 0;
     8         T->left = T->right = NULL;
     9     } /* if (插入空树) 结束 */
    10  
    11     else if ( X < T->data ) {
    12         T->left = Insert( T->left, X);/* 插入T的左子树 */
    13         if ( GetHeight(T->left)-GetHeight(T->right) == 2 ) /* 如果需要左旋 */
    14             if ( X < T->left->data ) 
    15                T = SingleLeftRotation(T);      //左单旋 LL
    16             else 
    17                T = DoubleLeftRightRotation(T); //左-右双旋LR
    18     } /* else if (插入左子树) 结束 */
    19      
    20     else if ( X > T->data ) {
    21         T->right = Insert( T->right, X );/* 插入T的右子树 */
    22         if ( GetHeight(T->left)-GetHeight(T->right) == -2 )/* 如果需要右旋 */
    23             if ( X > T->right->data ) 
    24                T = SingleRightRotation(T);     //右单旋 RR
    25             else 
    26                T = DoubleRightLeftRotation(T); //右-左双旋 RL
    27     } /* else if (插入右子树) 结束 */
    28  
    29     /*else X == T->Data,无须插入 */
    30     T->height = Max( GetHeight(T->left), GetHeight(T->right) ) + 1;    //更新树高 
    31      
    32     return T;
    33 }
    View Code
  • 相关阅读:
    双网卡主机无法管理的故障
    hosts文件导致无法访问网站
    获取webshell的十种方法
    XSS跨站攻击
    Ubuntu 使用中的问题总结
    ubuntu linux 13.04更新
    mysql root密码重置
    防火墙工作模式简介
    SE 2014年4月30日
    SE 2014年4月29日
  • 原文地址:https://www.cnblogs.com/kuotian/p/5333956.html
Copyright © 2011-2022 走看看