手把手教你写平衡二叉树
因為上BST課的時候睡覺睡過了結果。。。,后者折騰了一個下午才寫了出來,感謝http://blog.chinaunix.net/uid-24948645-id-3913917.html博客的詳細解析,但是上面的不足之處在于代碼是偽代碼,基本實現不了,然后自己做了修改,改成c++的寫法。
AVL樹平衡二叉樹數據結構AVL樹是最先發明的自平衡二叉查找算法,是平衡二叉樹的一種。在AVL中任何節點的兩個兒子子樹的高度最大差別為1,所以它又被成為高度平衡樹。查找、插入和刪除在平均和最壞情況下都是O(log n)。增加和刪除可能需要通過一次或多次樹旋轉來平衡這棵樹。
假設把AVL樹構造過程中需要重新平衡的節點叫做α。由于任意節點最多有兩個兒子,因此高度不平衡時,α點的兩顆子樹的高度差2。這種不平衡可能出現在下面這四種情況:
1)? 對α的左兒子的左子樹進行一次插入(右旋)
其中D是新插入的節點,紅色節點K2是失去平衡的節點。需要對K1和K2進行左旋調整即將K1作為根,將K2作為K1的左子樹,K1的右子樹調整為K2的左子樹。如下圖所示
進行右旋變換? ?
node* L_Ratate(node *K2) //左旋 {node *K1;K1 = K2->Left;K2->Left = K1->Right;K1->Right = K2;//更新節點的高度return K1; }2)對α的右兒子的右子樹進行一次插入(左旋)
將K2的右子樹更改為K1的左子樹,K1的左子樹更改為K2即完成的右旋,如下圖所示
進行左旋
node* R_Ratate(node* K2) {node* K1;K1 = K2->Right;K2->Right = K1->Left;K1->Left = K2;//更新節點高度return K1; }
3)對α的右兒子的左子樹進行一次插入(右左雙旋)
右左雙旋:先對K1和K2進行左旋,然后在對K2和K3進行右旋,最終實現平衡。如下圖所示
進行一次右旋進行一次左旋
node* DoubleL_Rotate(node* K3)//雙向旋轉(左右) {K3->Left = R_Ratate(K3->Left);return L_Ratate(K3); }4)對α的左兒子的右子樹進行一次插入(左右雙旋)
左右雙旋這里的左右指的是對α的左兒子的右子樹進行插入時需要旋轉。先對K1和K2進行右旋(跟第四種情況類似),然后再對K3和K2進行左旋,最終實現平衡。如下圖所示
進行一次左旋進行一次右旋
node* DoubleR_Rotate(node* K3)//雙向旋轉(右左) {K3->Right = L_Ratate(K3->Right);return R_Ratate(K3); }
完整代碼: #include<iostream> #include<algorithm> using namespace std; typedef struct Node {int data;int bf;//用來表示平衡因子struct Node *Left,*Right; } node; node* L_Ratate(node *K2) //左旋 {node *K1;K1 = K2->Left;K2->Left = K1->Right;K1->Right = K2;//更新節點的高度return K1; } node* R_Ratate(node* K2) {node* K1;K1 = K2->Right;K2->Right = K1->Left;K1->Left = K2;//更新節點高度return K1; } node* DoubleL_Rotate(node* K3)//雙向旋轉(左右) {K3->Left = R_Ratate(K3->Left);return L_Ratate(K3); } node* DoubleR_Rotate(node* K3)//雙向旋轉(右左) {K3->Right = L_Ratate(K3->Right);return R_Ratate(K3); } int Height(node* P) {if(P == NULL)return -1; //當構建根節點,或者是葉子節點的時候為-1+1正好為0elsereturn P->bf; }node* create_bst(node* bst,int x) {//cout<<"ok\n";if(!bst){//cout<<"ok\n";bst=new node;bst->data=x;bst->bf=0;bst->Left=bst->Right=NULL;}else if(x<bst->data){bst->Left=create_bst(bst->Left,x);if(Height(bst->Left)-Height(bst->Right)==2)//左子樹插入節點所以高度是左子樹高于右子樹{if(x<bst->Left->data)//對α的左兒子的左子樹進行一次插入,需要左旋bst=L_Ratate(bst);else//對α的左兒子的右子樹進行一次插入,需要雙旋bst=DoubleL_Rotate(bst);}}else if(x>bst->data)//右子樹插入新節點{bst->Right = create_bst(bst->Right,x);if(Height(bst->Right) - Height(bst->Left)== 2)//因為是右子樹插入新節點,所以高度是右子樹高于左子樹{if(x > bst->Right->data)//對α的右兒子的右子樹進行一次插入,需要右旋bst = R_Ratate(bst);else//對α的右兒子的左子樹進行一次插入,需要雙旋bst = DoubleR_Rotate(bst);}}bst->bf = max(Height(bst->Left), Height(bst->Right)) + 1;//cout<<"test="<<bst->bf<<endl;return bst; } void InOrder(node* bst) {if(!bst)return;else{InOrder(bst->Left);cout<<bst->data<<' '<<endl;InOrder(bst->Right);} } int main() {int n;cout<<"請輸入要構建的二叉平衡樹序列長度"<<endl;cin>>n;cout<<"請輸入要構建的二叉平衡樹序列"<<endl;node *bst=NULL;for(int i=0; i<n; ++i){int d;cin>>d;bst=create_bst(bst,d);}cout<<"....輸出...."<<endl;InOrder(bst);return 0; }
總結
以上是生活随笔為你收集整理的手把手教你写平衡二叉树的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: icpc大连栈
- 下一篇: html怎么设计自动出现提示的数据列表?