1. 程式人生 > >AVL平衡二叉樹的各種問題(Balanced Binary Tree)

AVL平衡二叉樹的各種問題(Balanced Binary Tree)

AVL樹或者是一棵空樹,或者是具有以下性質的非空二叉搜尋樹:

1. 任一結點的左、右子樹均為AVL樹;

2.根結點左、右子樹高度差的絕對值不超過1.

 

1.宣告

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef int ElementType;
typedef struct AVLNode * AVLTree; //AVL樹型別 
struct AVLNode{
    ElementType Data;    
//結點資料 AVLTree Left; //左子樹 AVLTree Right; //右子樹 int Height; //樹高 };
View Code

2.獲取高度

int GetHeight(AVLTree T){
    if(T) return max(GetHeight(T->Left ),GetHeight(T->Right )) + 1;
    else return 0;
}
View Code

3.左單旋LL

AVLTree SingleLeftRotation(AVLTree A){
    
// 注意:A 必須有一個左子結點 B // 將 A 與 B 左單選,更新 A 與 B 的高度,返回新的根結點 B AVLTree B = A->Left ; A->Left = B->Right ; B->Right = A; A->Height = max(GetHeight(A->Left ), GetHeight(A->Right )) + 1; B->Height = max(GetHeight(B->Left ),A->Height ) + 1; return B; }
View Code

4.右單旋RR

AVLTree SingleRightRotation(AVLTree A){
    AVLTree B = A->Right ;
    A->Right  = B->Left ;
    B->Left   = A;
    A->Height = max(GetHeight(A->Left ), GetHeight(A->Right )) + 1;
    B->Height = max(GetHeight(B->Right ),A->Height ) + 1;
    return B;
}
View Code

5.左-右雙旋LR

AVLTree DoubleLeftRightRotation(AVLTree A){
    // 注意:A必須有一個左子結點 B,且 B必須有一個右子結點 C
    // 將 A、B 與 C 做兩次單旋,返回新的根結點 C
    
    //將 B 與 C 做右單旋,C被返回 
    A->Left = SingleRightRotation(A->Left );
    //將 A 與 C 做左單旋,C被返回 
    return SingleLeftRotation(A);
}
View Code

6.右-左雙旋RL

AVLTree DoubleRightLeftRotation(AVLTree A){
    A->Right = SingleLeftRotation(A->Right );
    return SingleRightRotation(A);
}
View Code

7.AVL樹的插入

AVLTree Insert(AVLTree T, ElementType X){
    //將 X 插入AVL樹 T 中,並且返回調整後的AVL樹 
    if(! T){ //若插入空樹,則新建包含一個結點的樹 
        T = (AVLTree)malloc(sizeof(struct AVLNode));
        T->Data  = X;
        T->Height = 1;
        T->Left = T->Right = NULL;
    }
    else if(X < T->Data ){
        // 插入 T 的左子樹 
        T->Left =Insert(T->Left , X);
        // 如果需要左旋 
        if(GetHeight(T->Left ) - GetHeight(T->Right )== 2)
            if(X <T->Left ->Data)
                T = SingleLeftRotation(T); //左單旋 
            else
                T = DoubleLeftRightRotation(T); //左-右雙旋 
    }  
    else if(X > T->Data ){
        // 插入 T 的右子樹 
        T->Right  = Insert(T->Right , X);
        // 如果需要右旋 
        if(GetHeight(T->Left ) - GetHeight(T->Right )== -2)
            if(X > T->Right ->Data)
                T = SingleRightRotation(T); //右單選 
            else
                T = DoubleRightLeftRotation(T); //右-左雙旋 
    }
    // else X==T->Data 無需插入
    
    //更新樹高 
    T->Height = max(GetHeight(T->Left ),GetHeight(T->Right )) + 1;
    return T;
}
View Code

完整測試:

#include<iostream>
#include<cstdio>
#include<queue>
using namespace std;
typedef int ElementType;
typedef struct AVLNode * AVLTree;
struct AVLNode{
    ElementType Data;
    AVLTree Left;
    AVLTree Right;
    int Height; 
};
int GetHeight(AVLTree T){
    if(T) return max(GetHeight(T->Left ),GetHeight(T->Right )) + 1;
    else return 0;
}
AVLTree SingleLeftRotation(AVLTree A){
    AVLTree B = A->Left ;
    A->Left = B->Right ;
    B->Right  = A;
    A->Height = max(GetHeight(A->Left ), GetHeight(A->Right )) + 1;
    B->Height = max(GetHeight(B->Left ),A->Height ) + 1;
    return B;
}
AVLTree SingleRightRotation(AVLTree A){
    AVLTree B = A->Right ;
    A->Right  = B->Left ;
    B->Left   = A;
    A->Height = max(GetHeight(A->Left ), GetHeight(A->Right )) + 1;
    B->Height = max(GetHeight(B->Right ),A->Height ) + 1;
    return B;
}
AVLTree DoubleLeftRightRotation(AVLTree A){
    A->Left = SingleRightRotation(A->Left );
    return SingleLeftRotation(A);
}
AVLTree DoubleRightLeftRotation(AVLTree A){
    A->Right = SingleLeftRotation(A->Right );
    return SingleRightRotation(A);
}
AVLTree Insert(AVLTree T, ElementType X){
    if(! T){
        T = (AVLTree)malloc(sizeof(struct AVLNode));
        T->Data  = X;
        T->Height = 1;
        T->Left = T->Right = NULL;
    }
    else if(X < T->Data ){
        T->Left =Insert(T->Left , X);
        if(GetHeight(T->Left ) - GetHeight(T->Right )== 2)
            if(X <T->Left ->Data)
                T = SingleLeftRotation(T);
            else
                T = DoubleLeftRightRotation(T);
    }
    else if(X > T->Data ){
        T->Right  = Insert(T->Right , X);
        if(GetHeight(T->Left ) - GetHeight(T->Right )== -2)
            if(X > T->Right ->Data)
                T = SingleRightRotation(T);
            else
                T = DoubleRightLeftRotation(T);
    }
    T->Height = max(GetHeight(T->Left ),GetHeight(T->Right )) + 1;
    return T;
}
void LevelorderTravelsal(AVLTree BT){
    queue<AVLTree> q;
    AVLTree T;
    if(!BT) return;
    q.push(BT);
    while(!q.empty()){
        T=q.front();
        q.pop();
        cout<<T->Data <<" ";
        if(T->Left ) q.push(T->Left );
        if(T->Right ) q.push(T->Right );
    }
} 
int main(){
    int n; cin>>n;
    AVLTree T = NULL;
    for(int i=0;i<n;i++){
        int x; cin>>x;
        T = Insert(T, x);
    }
    LevelorderTravelsal(T);
}
View Code