程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> C語言 >> 關於C語言 >> 平衡二叉樹(AVL)的實現,附可運行C語言代碼

平衡二叉樹(AVL)的實現,附可運行C語言代碼

編輯:關於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     else 15         phead->lchild = NULL; 16  17     temp->rchild = phead; 18     if(temp->rchild->data == 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     else 15         phead->rchild = NULL; 16  17     temp->lchild = phead; 18     if(temp->lchild->data == 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     else 33         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 == 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 = 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                 else 25                     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 = 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                 else 53                     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 == 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             else 37                 (*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             else 48                 (*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     else 93         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 復制代碼 源文件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 = 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 == 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 = 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 = 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                 else 124                     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為1 149  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 == 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             else 180                 (*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             else 191                 (*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     else 236         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 == 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         else 269             return 0; 270     } 271     else 272         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 == 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     else 312         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     else 329         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,每多一層高度加1 370     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     else 400         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     else 417         phead->lchild = NULL; 418  419     temp->rchild = phead; 420     if(temp->rchild->data == 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     else 445         phead->rchild = NULL; 446  447     temp->lchild = phead; 448     if(temp->lchild->data == 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 }

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved