数据结构与算法——图解平衡二叉树及代码实现
平衡二叉樹介紹
平衡二叉樹,是一種二叉排序樹,其中每一個節點的左子樹和右子樹的高度差最多等于1。由3位科學家共同發明,用他們首字母命名 又被稱為AVL樹。從平衡二叉樹的名稱,你也可以體會到它是一種高度平衡的二叉排序樹。我們將二叉樹上結點的左子樹深度減去右子樹的深度的值稱為平衡因子BF,那么平衡二叉樹上的所有結點的平衡因子只能是-1,0,1。
平衡二叉樹的實現原理
平衡二叉樹構建的基本思想就在在構建二叉排序樹的過程中,每當插入一個結點時,先檢查否是因為插入而破壞了樹的平衡性,若是,這找出最小不平衡樹,在滿足二叉排序樹的特點,將其調整成新的平衡二叉樹。
旋轉圖解
在理解平衡二叉樹代碼之前,我們得理解樹的旋轉,在下面的一系列圖中,字母并無實際意義不代表其數據域,就是一個標識,但是要想著他們都是滿足二叉排序的特性,在這個特性之上進行旋轉。
對樹節點進行左右旋轉
下面2圖是最基本的左右旋轉,理解后,對應的旋轉代碼就好理解了。
雙旋轉的情況
讓其左平衡,進行右旋轉,讓其右平衡進行左旋轉。T代表要旋轉的樹節點,L = T->lchild,Lr = L-rchild;R = T->rchild,Rl = R->lchild;
但是要注意下面情況:
某個樹節點T插入結點后,如果其左不平衡bf > 0,我們通過旋轉讓其左平衡。此時,其 L 左孩子的 bf 會影響如何旋轉,如果L->bf = 1 同 T 方向一致,這是最簡單的情況,只需將T進行右旋轉。右平衡也是一樣的道理。如果L->bf 和 T的方向不一致,那么就要先通過左旋轉 讓T->lchild和 T的方向一致,T在進行右旋轉。
結合代碼很好看明白。
左平衡情況
右平衡情況
實現代碼
下面主要是平衡二叉樹的插入算法,平衡二叉樹的主要算法也就是插入算法。它的刪除和查找同二叉排序樹是一樣的這里就多寫了,有興趣可以看數據結構與算法——二叉排序樹詳解以及代碼實現。
#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> #include <stdlib.h> typedef struct BiTNode {int data;int bf;struct BiTNode* lchild, *rchild; }BiTNode, *BiTree; typedef enum{false,true}bool; //左旋轉 void L_Rotate(BiTree *T) {BiTree R = (*T)->rchild;(*T)->rchild = R->lchild;R->lchild = *T;*T = R;return; } //右旋轉 void R_Rotate(BiTree *T) {BiTree L = (*T)->lchild;(*T)->lchild = L->rchild;L->rchild = *T;*T = L;return; } #define LH +1 #define EH 0 #define RH -1 //T 的左邊高,不平衡,使其平衡,右旋轉,右旋轉前先檢查L->bf, //如果為RH,L要先進行左旋轉,使T->lchild->bf和T->bf一致 void LeftBalance(BiTree* T) {BiTree L,Lr;L = (*T)->lchild;Lr = L->rchild;switch (L->bf){case LH:L->bf = (*T)->bf = EH;R_Rotate(T);break;case RH:switch (Lr->bf){case LH:L->bf = EH;(*T)->bf = RH;break;case EH:L->bf = (*T)->bf = EH;break;case RH:L->bf = LH;(*T)->bf = EH;break;}Lr->bf = EH;L_Rotate(&L);R_Rotate(T);break;} } //T 的右邊高,不平衡,使其平衡,左旋轉,左旋轉前先檢查R->bf, //如果為LH,R要先進行右旋轉,使T->rchild->bf和T->bf一致 void RightBalance(BiTree* T) {BiTree R,Rl;R = (*T)->rchild;Rl = R->lchild;switch(R->bf){case RH:R->bf = (*T)->bf = EH;L_Rotate(T);break;case LH:switch(R->bf){case LH:R->bf = RH;(*T)->bf = EH;break;case EH:R->bf = (*T)->bf = EH;break;case RH:R->bf = EH;(*T)->bf = LH;break;}Rl->bf = EH;R_Rotate(&R);L_Rotate(T);break;} } //往平衡二叉樹上插入結點 bool InsertAVL(BiTree* T,int data,bool *taller) {if(*T == NULL) //找到插入位置{*T = (BiTree)malloc(sizeof(BiTNode)); (*T)->bf = EH;(*T)->rchild = (*T)->lchild = NULL;(*T)->data = data; *taller = true;}else{if(data == (*T)->data) //樹中有相同的結點數據直接返回{*taller = false;return false;}if(data < (*T)->data) //往左子樹搜索進行插入{if(!InsertAVL(&(*T)->lchild,data,taller)) //樹中有相同的結點{*taller = false;return false;} if (*taller){switch ((*T)->bf) //T插入結點后,檢測平衡因子,根據情況,做相應的修改和旋轉{case LH:LeftBalance(T); //插入后左邊不平衡了,讓其左平衡*taller = false;break;case EH:(*T)->bf = LH;*taller = true;break;case RH:(*T)->bf = EH;*taller = false;break;}}}else //往右子樹搜索進行插入{if(!Insert(&(*T)->rchild),data,taller) //樹中有相同的結點{*taller = false;return false;}if (*taller) //插入到右子樹中且長高了{switch ((*T)->bf) //T插入結點后,檢測平衡因子,根據情況,做相應的修改和旋轉{case LH:(*T)->bf = EH;*taller = false;break;case EH:(*T)->bf = RH;*taller = true;break;case RH:R_Balance(T); //插入后右邊不平衡了,讓其右平衡*taller = false;break;}}}}return true; }總結
以上是生活随笔為你收集整理的数据结构与算法——图解平衡二叉树及代码实现的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++ WINDOWS下 wchar_t
- 下一篇: Qt:Qt实现飞秋拦截助手—ARP攻击