首页 > 代码库 > 平衡二叉树(AVL)的实现,附可运行C语言代码

平衡二叉树(AVL)的实现,附可运行C语言代码

最近几月一直在自学C语言和数据结构,先是写了排序二叉树,觉得平衡二叉树作为一个经典数据结构,有必要实现一下。

网上看了些资料,在AVL和红黑树之间考虑,最后个人还是倾向于AVL。

不同于标准AVL的是,笔者没有使用平衡因子,直接根据左右孩子的高度差值判断是否平衡。整个平衡二叉树是在普通二叉查找树的基础上修改得到的,对于学习数据结构的同学来说,这样逐步提高难度,写起来挑战性没那么大。

代码经测试是可以运行,并实现插入、删除、修改节点时都可以保持平衡。相对于普通二叉查找树,AVL在查找时效率高耗时短,但为了保持高度平衡,必须牺牲插入和删除操作的复杂度。本文将分步讲解如何编写平衡二叉树,全文最后附有完整代码。

当左右子树的高度差超过1时(即≥2,在实际处理时,等于2即为不平衡,进行调整操作,所以不会出现大于2的情况),整棵树失去平衡。写代码之前先了解AVL是如何使二叉树保持平衡,这里涉及到对节点的旋转操作,分四种情况,左左,右右,左右,右左。下面分别解释:

一、左左单旋转

在节点x的左孩子插入节点b

①x无右孩子,旋转节点a即可达到平衡

②x有右孩子c,旋转节点a后,根据a>c>x,需将节点c移动到a的左子树

函数代码如下:

 1 static BTNode *singleRotateLL(BTree *BT, BTNode *phead) 2 {//不平衡情况为左左的单旋转操作 3     BTNode *temp; 4  5     if(phead == NULL) 6         return 0; 7  8     temp = phead->lchild; 9     10     if(temp->rchild != NULL){11         phead->lchild = temp->rchild;12         phead->lchild->height = tree_node_height(BT, phead->lchild);13     }14     else15         phead->lchild = NULL;16 17     temp->rchild = phead;18     if(temp->rchild->data =http://www.mamicode.com/= BT->phead->data){19         BT->phead = temp;20     }21     phead = temp;22     temp->rchild->height = tree_node_height(BT, temp->rchild);23     temp->height = tree_node_height(BT, temp);24     phead->height = tree_node_height(BT, phead);25     26     return phead;27 }

二、右右单旋转

在节点x的右孩子插入节点b

①x无左孩子,旋转节点a即可达到平衡

②x有左孩子c,旋转节点a后,根据x>c>a,需将节点c移动到a的右子树

函数代码如下:

 1 static BTNode *singleRotateRR(BTree *BT, BTNode *phead) 2 {//不平衡情况为右右的单旋转操作 3     BTNode *temp; 4  5     if(phead == NULL) 6         return 0; 7  8     temp = phead->rchild; 9 10     if(temp->lchild != NULL){11         phead->rchild = temp->lchild;12         phead->rchild->height = tree_node_height(BT, phead->rchild);13     }14     else15         phead->rchild = NULL;16 17     temp->lchild = phead;18     if(temp->lchild->data =http://www.mamicode.com/= BT->phead->data){19         BT->phead = temp;20     }21     phead = temp;22     temp->lchild->height = tree_node_height(BT, temp->lchild);23     temp->height = tree_node_height(BT, temp);24     phead->height = tree_node_height(BT, phead);25 26     return phead;27 }

注:需要注意的是节点旋转后,节点赋值和高度的更新,初学者很容易忽略或是弄错赋值顺序

三、左右双旋转

在节点x的右孩子插入节点b

①x无左孩子,②x有左孩子c,这两种情况的处理相同,首先对x节点进行右右单旋转操作,然后对a节点进行左左单旋转操作

函数代码如下:

 1 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead) 2 {//不平衡情况为左右的双旋转操作 3     BTNode *temp; 4  5     if(phead == NULL) 6         return 0; 7  8     temp = phead->lchild;     9     phead->lchild = singleRotateRR(BT, temp);10     temp = phead;11     phead = singleRotateLL(BT, temp);12 13     return phead;14 }

四、右左双旋转

在节点x的右孩子插入节点b

①x无右孩子,②x有右孩子c,这两种情况的处理相同,首先对x节点进行左左单旋转操作,然后对a节点进行右右单旋转操作

函数代码如下:

 1 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead) 2 {//不平衡情况为右左的双旋转操作 3     BTNode *temp; 4  5     if(phead == NULL) 6         return 0; 7  8     temp = phead->rchild; 9     phead->rchild = singleRotateLL(BT, temp);10     temp = phead;11     phead = singleRotateRR(BT, temp);12 13     return phead;14 }

 

弄清楚了怎样通过旋转达到平衡状态,接下来一步一步构造平衡二叉树。

第一步,我们要在二叉树的节点中加一个属性:高度,在后面的插入和删除函数中将会用到。

结构体代码如下:

1 typedef struct _BTNode{2     TYPE data;3     int height;         4     struct _BTNode *lchild;5     struct _BTNode *rchild;6 }BTNode;

 

第二步,需要添加三个辅助函数,一是求节点的高度,而是遍历求树中每个节点的高度(在删除函数中会用到),三是求两个高度的最大值。

 1 static int tree_node_height(BTree *BT, BTNode *phead) 2 {//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1 3     if(phead != NULL){ 4         if(phead->lchild == NULL && phead->rchild == NULL){ 5             return 0; 6         } 7         else{ 8             return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + 1; 9         }10     }11     else{12         return -1;13     }14 }15 16 static void tree_height(BTree *BT, BTNode *phead)17 {//遍历求树中每个节点的高度18     if(phead == NULL)19         return;20 21     tree_node_height(BT, phead);22     if(phead->lchild != NULL)23         tree_node_height(BT, phead->lchild);24     if(phead->rchild != NULL)25         tree_node_height(BT, phead->rchild);26 }27 28 static int max_height(int height1, int height2)29 {//求两个高度的最大值30     if(height1 > height2)31         return height1;32     else33         return height2;34 }

 第三步,插入

 插入操作与二叉查找树的操作基本相同,只是在插入后需判断是否平衡,如果不平衡,进行旋转调整。因为BTNode没有使用父节点属性,所以需要用变量存储插入位置,以便调整后可以接回到二叉树上。树顶的根节点需特殊处理

 1 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value) 2 {//按序插入结点 3     if(phead == NULL) 4         return 0; 5  6     if(phead->data =http://www.mamicode.com/= value) 7         return 0; 8  9     else{10         if(phead->data > value){11             if(phead->lchild == NULL){12                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));13                 newnode->data =http://www.mamicode.com/ value;14                 newnode->lchild = newnode->rchild = NULL;15                 phead->lchild = newnode;16             }17             else{18                 tree_add(BT, phead->lchild, value);19 20                 //判断插入节点后是否平衡,并调整21                 BTNode *root;22                 if(phead = BT->phead)23                     root = phead;24                 else25                     root = phead->lchild;26             27                 if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == 2){28                     if(root->lchild->data > value){29                         root = singleRotateLL(BT, root);30                     }31                     else{32                         root = doubleRotateLR(BT, root);33                     }34                 }35                 phead = root;36             }37         }38         else{39             if(phead->rchild == NULL){40                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));41                 newnode->data =http://www.mamicode.com/ value;42                 newnode->lchild = newnode->rchild = NULL;43                 phead->rchild = newnode;                    44             }45             else{46                 tree_add(BT, phead->rchild, value);47                 48                 //判断插入节点后是否平衡,并调整49                 BTNode *root;50                 if(phead = BT->phead)51                     root = phead;52                 else53                     root = phead->rchild;54                     55                 if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == 2){56                     if(root->rchild->data < value){57                         root = singleRotateRR(BT, root);58                     }59                     else{60                         root = doubleRotateRL(BT, root);61                     }62                 }63                 phead = root;64             }            65         }66             phead->height = tree_node_height(BT, phead);67             return 1;68     }69 70     return 0;71 }

第四步,删除

平衡二叉树的删除操作比插入更复杂,因为删除后会引起一系列节点高度的改变,删除后将剩余子树接回二叉树时,要分三种情况处理,被删除节点是:顶部根节点、底部叶子(无子树)、普通节点。

 1 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value) 2 {//删除结点 3     BTNode *temp; 4     BTNode *root; 5     int flag;        //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1 6  7     if(*phead == NULL) 8         return 0; 9         10     if(*phead == BT->phead){11         flag = 0;12         root = *phead;13     }14 15     else if((*phead)->lchild != NULL){16         flag = -1;17         root = (*phead)->lchild;18     }19 20     else if((*phead)->rchild != NULL){21         flag = 1;22         root = (*phead)->rchild;23     }24     else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)25         root = *phead;26     27     if(root->data =http://www.mamicode.com/= value){28         if(root->lchild != NULL){29             temp = BT->search_max(BT, &root->lchild, 1);30             temp->lchild = root->lchild;31              temp->rchild = root->rchild;32             free(root);33             root = temp;34             if(flag == 0)35                 BT->phead = root;36             else37                 (*phead)->lchild = root;38         }39         else if(root->rchild != NULL){40             temp = BT->search_min(BT, &root->rchild, 1);   41             temp->lchild = root->lchild;42             temp->rchild = root->rchild;43             free(root);44             root = temp;45             if(flag == 0)46                 BT->phead = root;47             else48                 (*phead)->rchild = root;49         }50         else{51             if(flag == 0)52                 free(*phead);53             else if(flag = -1){54                 free((*phead)->lchild);55                 (*phead)->lchild = NULL;56             }57             else if(flag = 1){58                 free((*phead)->rchild);59                 (*phead)->rchild = NULL;60             }61         }62          63         tree_height(BT, BT->phead);    //删除节点后,求每个节点的新高度64 65         if(flag == 0)66             return 1;67         if(flag == -1){68             if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == 2){69                 if((*phead)->rchild->rchild != NULL){70                     root = singleRotateRR(BT, *phead);71                 }72                 else{73                     root = doubleRotateRL(BT, *phead);74                 }75             }76         }77         else{78             if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == 2){79                 if((*phead)->lchild->lchild != NULL){80                     root = singleRotateLL(BT, *phead);81                 }82                 else{83                     root = doubleRotateLR(BT, *phead);84                 }85             }86         }87             88         return 1;89     }90     else if(root->data > value)91         return BT->del(BT, &root->lchild, value);92     else93         return BT->del(BT, &root->rchild, value);94 95     return 0;96 }

 

除了插入和删除操作,其他操作均与普通二叉查找树一样。

如果读者发现错误或有更好的处理方法,请指出,以便修改完善。 

 

头文件binary.h代码:

 1 #ifndef BINARY_H 2 #define BINARY_H 3  4 typedef int TYPE; 5 typedef int BOOL; 6  7 typedef struct _BTNode{ 8     TYPE data; 9     int height;         10     struct _BTNode *lchild;11     struct _BTNode *rchild;12 }BTNode;13 14 typedef struct _BTree{15     BTNode *phead;    16 17     void(*init)(struct _BTree *BT, TYPE head_value);18     void(*exit)(struct _BTree *BT);19     void(*print)(struct _BTree *BT, BTNode *phead);20 21     BOOL(*add)(struct _BTree *BT, BTNode *phead, TYPE value);22     BOOL(*del)(struct _BTree *BT, BTNode **phead, TYPE value);23     BOOL(*del_tree)(struct _BTree *BT, BTNode **phead);24     BOOL(*alter)(struct _BTree *BT, BTNode *phead, TYPE value, TYPE new_value);25     BTNode *(*search)(struct _BTree *BT, BTNode *phead, TYPE value);26 27     BTNode *(*search_min)(struct _BTree *BT, BTNode **phead, int flag);28     BTNode *(*search_max)(struct _BTree *BT, BTNode **phead, int flag);    29 30     void(*pre_traverse)(struct _BTree *BT, BTNode *phead);31     void(*mid_traverse)(struct _BTree *BT, BTNode *phead);32     void(*last_traverse)(struct _BTree *BT, BTNode *phead);33 34     //以下为实现AVL所需函数35     int (*node_height)(_BTree *BT, BTNode *phead);36     void (*height)(_BTree *BT, BTNode *phead);37     int (*max_height)(int height1, int height2);38     BTNode *(*singleRotateLL)(_BTree *BT, BTNode *phead);39     BTNode *(*singleRotateRR)(_BTree *BT, BTNode *phead);40     BTNode *(*doubleRotateLR)(_BTree *BT, BTNode *phead);41     BTNode *(*doubleRotateRL)(_BTree *BT, BTNode *phead);42 }BTree;43 44 void tree_init(BTree *BT, TYPE value);45 void tree_exit(BTree *BT);46 47 #endif
View Code

源文件binary.cpp代码:

  1 #include <stdio.h>  2 #include <string.h>  3 #include <stdlib.h>  4   5 #include "binary.h"  6   7 void tree_init(BTree *BT, TYPE head_value);  8 void tree_exit(BTree *BT);  9 void tree_print(BTree *BT, BTNode *phead); 10 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value); 11 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value); 12 static BOOL tree_del_tree(BTree *BT, BTNode **phead); 13 static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value); 14 static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value); 15 static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag); 16 static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag); 17 static void tree_pre_traverse(BTree *BT, BTNode *phead); 18 static void tree_mid_traverse(BTree *BT, BTNode *phead); 19 static void tree_last_traverse(BTree *BT, BTNode *phead); 20  21 //以下为实现AVL所需函数 22 static int tree_node_height(BTree *BT, BTNode *phead); 23 static void tree_height(BTree *BT, BTNode *phead); 24 static int max_height(int height1, int height2); 25 static BTNode *singleRotateLL(BTree *BT, BTNode *phead); 26 static BTNode *singleRotateRR(BTree *BT, BTNode *phead); 27 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead); 28 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead); 29  30  31 void tree_init(BTree *BT, TYPE head_value) 32 {//初始化 33     BT->phead = (BTNode*)calloc(1, sizeof(BTNode)); 34     BT->phead->data =http://www.mamicode.com/ head_value; 35      36     BT->phead->lchild = BT->phead->rchild = NULL; 37  38     BT->add = tree_add; 39     BT->del = tree_del; 40     BT->print = tree_print; 41     BT->del_tree = tree_del_tree; 42     BT->alter = tree_alter; 43     BT->search = tree_search; 44     BT->search_min = tree_search_min; 45     BT->search_max = tree_search_max; 46     BT->pre_traverse = tree_pre_traverse; 47     BT->mid_traverse = tree_mid_traverse; 48     BT->last_traverse = tree_last_traverse; 49     BT->exit = tree_exit; 50  51     BT->node_height = tree_node_height; 52     BT->height = tree_height; 53     BT->max_height = max_height; 54     BT->singleRotateLL = singleRotateLL; 55     BT->singleRotateRR = singleRotateRR; 56     BT->doubleRotateLR = doubleRotateLR; 57     BT->doubleRotateRL = doubleRotateRL; 58 } 59  60 void tree_exit(BTree *BT) 61 {//结束操作 62     if(BT != NULL) 63         BT->del_tree(BT, &BT->phead); 64 } 65  66 void tree_print(BTree *BT, BTNode *phead) 67 {//打印结点 68     if(phead != NULL) 69         printf("%d\n", phead->data); 70 } 71  72 static BOOL tree_add(BTree *BT, BTNode *phead, TYPE value) 73 {//按序插入结点 74     if(phead == NULL) 75         return 0; 76  77     if(phead->data =http://www.mamicode.com/= value) 78         return 0; 79  80     else{ 81         if(phead->data > value){ 82             if(phead->lchild == NULL){ 83                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode)); 84                 newnode->data =http://www.mamicode.com/ value; 85                 newnode->lchild = newnode->rchild = NULL; 86                 phead->lchild = newnode; 87             } 88             else{ 89                 tree_add(BT, phead->lchild, value); 90  91                 //判断插入节点后是否平衡,并调整 92                 BTNode *root; 93                 if(phead = BT->phead) 94                     root = phead; 95                 else 96                     root = phead->lchild; 97              98                 if(tree_node_height(BT, root->lchild) - tree_node_height(BT, root->rchild) == 2){ 99                     if(root->lchild->data > value){100                         root = singleRotateLL(BT, root);101                     }102                     else{103                         root = doubleRotateLR(BT, root);104                     }105                 }106                 phead = root;107             }108         }109         else{110             if(phead->rchild == NULL){111                 BTNode *newnode = (BTNode*)calloc(1, sizeof(BTNode));112                 newnode->data =http://www.mamicode.com/ value;113                 newnode->lchild = newnode->rchild = NULL;114                 phead->rchild = newnode;                    115             }116             else{117                 tree_add(BT, phead->rchild, value);118                 119                 //判断插入节点后是否平衡,并调整120                 BTNode *root;121                 if(phead = BT->phead)122                     root = phead;123                 else124                     root = phead->rchild;125                     126                 if(tree_node_height(BT, root->rchild) - tree_node_height(BT, root->lchild) == 2){127                     if(root->rchild->data < value){128                         root = singleRotateRR(BT, root);129                     }130                     else{131                         root = doubleRotateRL(BT, root);132                     }133                 }134                 phead = root;135             }            136         }137             phead->height = tree_node_height(BT, phead);138             return 1;139     }140 141     return 0;142 }143 144 static BOOL tree_del(BTree *BT, BTNode **phead, TYPE value)145 {//删除结点146     BTNode *temp;147     BTNode *root;148     int flag;        //flag标记被删除的节点,默认顶部节点flag为0,左边节点flag为-1,右边节点flag为1149 150     if(*phead == NULL)151         return 0;152         153     if(*phead == BT->phead){154         flag = 0;155         root = *phead;156     }157 158     else if((*phead)->lchild != NULL){159         flag = -1;160         root = (*phead)->lchild;161     }162 163     else if((*phead)->rchild != NULL){164         flag = 1;165         root = (*phead)->rchild;166     }167     else if((*phead)->lchild == NULL && (*phead)->rchild == NULL)168         root = *phead;169     170     if(root->data =http://www.mamicode.com/= value){171         if(root->lchild != NULL){172             temp = BT->search_max(BT, &root->lchild, 1);173             temp->lchild = root->lchild;174              temp->rchild = root->rchild;175             free(root);176             root = temp;177             if(flag == 0)178                 BT->phead = root;179             else180                 (*phead)->lchild = root;181         }182         else if(root->rchild != NULL){183             temp = BT->search_min(BT, &root->rchild, 1);   184             temp->lchild = root->lchild;185             temp->rchild = root->rchild;186             free(root);187             root = temp;188             if(flag == 0)189                 BT->phead = root;190             else191                 (*phead)->rchild = root;192         }193         else{194             if(flag == 0)195                 free(*phead);196             else if(flag = -1){197                 free((*phead)->lchild);198                 (*phead)->lchild = NULL;199             }200             else if(flag = 1){201                 free((*phead)->rchild);202                 (*phead)->rchild = NULL;203             }204         }205          206         tree_height(BT, BT->phead);    //删除节点后,求每个节点的新高度207 208         if(flag == 0)209             return 1;210         if(flag == -1){211             if(tree_node_height(BT, (*phead)->rchild) - tree_node_height(BT, (*phead)->lchild) == 2){212                 if((*phead)->rchild->rchild != NULL){213                     root = singleRotateRR(BT, *phead);214                 }215                 else{216                     root = doubleRotateRL(BT, *phead);217                 }218             }219         }220         else{221             if(tree_node_height(BT, (*phead)->lchild) - tree_node_height(BT, (*phead)->rchild) == 2){222                 if((*phead)->lchild->lchild != NULL){223                     root = singleRotateLL(BT, *phead);224                 }225                 else{226                     root = doubleRotateLR(BT, *phead);227                 }228             }229         }230             231         return 1;232     }233     else if(root->data > value)234         return BT->del(BT, &root->lchild, value);235     else236         return BT->del(BT, &root->rchild, value);237 238     return 0;239 }240 241 static BOOL tree_del_tree(BTree *BT, BTNode **phead)242 {//删除二叉树243     if(*phead == NULL)244         return 0;245     246     if((*phead)->lchild != NULL)247         BT->del_tree(BT, &(*phead)->lchild);248     if((*phead)->rchild != NULL)249         BT->del_tree(BT, &(*phead)->rchild);250 251     free(*phead);252     *phead = NULL;253 254     return 1;255 }256 257 static BOOL tree_alter(BTree *BT, BTNode *phead, TYPE value, TYPE new_value)258 {//更改结点的值(先删除,后插入)259     if(phead == NULL)260         return 0;261 262     if(value =http://www.mamicode.com/= new_value)263         return 1;264 265     if(BT->del(BT, &phead, value) != 0){266         if(BT->add(BT, phead, new_value) != 0)267             return 1;268         else269             return 0;270     }271     else272         return 0;273 }274 275 static BTNode *tree_search(BTree *BT, BTNode *phead, TYPE value)276 {//查找结点277     BTNode *temp;278 279     if(phead == NULL)280         return NULL;281 282     if(phead->data =http://www.mamicode.com/= value)283         return phead;284     if(phead->lchild != NULL){285         temp = BT->search(BT, phead->lchild, value);286         if(temp != NULL)287             return temp;288     }289     if(phead->rchild != NULL){290         temp = BT->search(BT, phead->rchild, value);291         if(temp != NULL)292             return temp;293     }294 295     return NULL;296 }297 298 static BTNode *tree_search_min(BTree *BT, BTNode **phead, int flag)299 {//查找最小结点300     BTNode *temp;301 302     if(*phead == NULL)303         return NULL;304 305     if((*phead)->lchild == NULL){306         temp = *phead;307         if(flag == 1)308             *phead = (*phead)->rchild;309         return temp;310     }311     else312         return BT->search_min(BT, &(*phead)->lchild, flag);313 }314 315 static BTNode *tree_search_max(BTree *BT, BTNode **phead, int flag)316 {//查找最大结点317     BTNode *temp;318 319     if(*phead == NULL)320         return NULL;321 322     if((*phead)->rchild == NULL){323         temp = *phead;324         if(flag == 1)325             *phead = (*phead)->lchild;326         return temp;327     }328     else329         return BT->search_max(BT, &(*phead)->rchild, flag);330 }331 332 static void tree_pre_traverse(BTree *BT, BTNode *phead)333 {//先序遍历二叉树334     if(phead == NULL)335         return;336 337     BT->print(BT, phead);338     if(phead->lchild != NULL)339         BT->pre_traverse(BT, phead->lchild);340     if(phead->rchild != NULL)341         BT->pre_traverse(BT, phead->rchild);342 }343 344 static void tree_mid_traverse(BTree *BT, BTNode *phead)345 {//中序遍历二叉树346     if(phead == NULL)347         return;348 349     if(phead->lchild != NULL)350         BT->mid_traverse(BT, phead->lchild);351     BT->print(BT, phead);352     if(phead->rchild != NULL)353         BT->mid_traverse(BT, phead->rchild);354 }355 356 static void tree_last_traverse(BTree *BT, BTNode *phead)357 {//后序遍历二叉树358     if(phead == NULL)359         return;360 361     if(phead->lchild != NULL)362         BT->last_traverse(BT, phead->lchild);363     if(phead->rchild != NULL)364         BT->last_traverse(BT, phead->rchild);365     BT->print(BT, phead);366 }367 368 static int tree_node_height(BTree *BT, BTNode *phead)369 {//求节点的高度,写成函数解决指针为空的情况,默认空节点的高度为-1,只有一个根节点的节点的高度为0,每多一层高度加1370     if(phead != NULL){371         if(phead->lchild == NULL && phead->rchild == NULL){372             return 0;373         }374         else{375             return phead->height = max_height(tree_node_height(BT, phead->lchild), tree_node_height(BT, phead->rchild)) + 1;376         }377     }378     else{379         return -1;380     }381 }382 383 static void tree_height(BTree *BT, BTNode *phead)384 {//遍历求树中每个节点的高度385     if(phead == NULL)386         return;387 388     tree_node_height(BT, phead);389     if(phead->lchild != NULL)390         tree_node_height(BT, phead->lchild);391     if(phead->rchild != NULL)392         tree_node_height(BT, phead->rchild);393 }394 395 static int max_height(int height1, int height2)396 {//求两个高度的最大值397     if(height1 > height2)398         return height1;399     else400         return height2;401 }402 403 static BTNode *singleRotateLL(BTree *BT, BTNode *phead)404 {//不平衡情况为左左的单旋转操作405     BTNode *temp;406 407     if(phead == NULL)408         return 0;409 410     temp = phead->lchild;411     412     if(temp->rchild != NULL){413         phead->lchild = temp->rchild;414         phead->lchild->height = tree_node_height(BT, phead->lchild);415     }416     else417         phead->lchild = NULL;418 419     temp->rchild = phead;420     if(temp->rchild->data =http://www.mamicode.com/= BT->phead->data){421         BT->phead = temp;422     }423     phead = temp;424     temp->rchild->height = tree_node_height(BT, temp->rchild);425     temp->height = tree_node_height(BT, temp);426     phead->height = tree_node_height(BT, phead);427     428     return phead;429 }430 431 static BTNode *singleRotateRR(BTree *BT, BTNode *phead)432 {//不平衡情况为右右的单旋转操作433     BTNode *temp;434 435     if(phead == NULL)436         return 0;437 438     temp = phead->rchild;439 440     if(temp->lchild != NULL){441         phead->rchild = temp->lchild;442         phead->rchild->height = tree_node_height(BT, phead->rchild);443     }444     else445         phead->rchild = NULL;446 447     temp->lchild = phead;448     if(temp->lchild->data =http://www.mamicode.com/= BT->phead->data){449         BT->phead = temp;450     }451     phead = temp;452     temp->lchild->height = tree_node_height(BT, temp->lchild);453     temp->height = tree_node_height(BT, temp);454     phead->height = tree_node_height(BT, phead);455 456     return phead;457 }458 static BTNode *doubleRotateLR(BTree *BT, BTNode *phead)459 {//不平衡情况为左右的双旋转操作460     BTNode *temp;461 462     if(phead == NULL)463         return 0;464 465     temp = phead->lchild;    466     phead->lchild = singleRotateRR(BT, temp);467     temp = phead;468     phead = singleRotateLL(BT, temp);469 470     return phead;471 }472 473 static BTNode *doubleRotateRL(BTree *BT, BTNode *phead)474 {//不平衡情况为右左的双旋转操作475     BTNode *temp;476 477     if(phead == NULL)478         return 0;479 480     temp = phead->rchild;481     phead->rchild = singleRotateLL(BT, temp);482     temp = phead;483     phead = singleRotateRR(BT, temp);484 485     return phead;486 }487 488 int main(int argc, char* argv[])489 {//测试490     BTree testtree;491     testtree.init = tree_init;492     testtree.init(&testtree, 9);493 494     testtree.add(&testtree, testtree.phead, 4);495     testtree.add(&testtree, testtree.phead, 5);496     testtree.add(&testtree, testtree.phead, 6);497     testtree.add(&testtree, testtree.phead, 1);498     testtree.add(&testtree, testtree.phead, 7);499     testtree.add(&testtree, testtree.phead, 8);500     testtree.add(&testtree, testtree.phead, 11);501     testtree.add(&testtree, testtree.phead, 10);502 503     testtree.pre_traverse(&testtree, testtree.phead);504     printf("\n");505     testtree.mid_traverse(&testtree, testtree.phead);506     printf("\n");507     testtree.last_traverse(&testtree, testtree.phead);508     printf("\n");509 510     printf("%d\n", (testtree.search(&testtree, testtree.phead, 8))->data);511     printf("\n");512 513     testtree.del(&testtree, &testtree.phead, 4);514     testtree.del(&testtree, &testtree.phead, 1);515     testtree.del(&testtree, &testtree.phead, 6);516     testtree.alter(&testtree, testtree.phead, 9, 2);517 518     testtree.pre_traverse(&testtree, testtree.phead);519     printf("\n");520     testtree.mid_traverse(&testtree, testtree.phead);521     printf("\n");522     testtree.last_traverse(&testtree, testtree.phead);523     printf("\n");524 525     return 0;526 }
View Code

 

平衡二叉树(AVL)的实现,附可运行C语言代码