1. 程式人生 > >PTA Root of AVL Tree (AVL樹模板+四種旋轉+指針)

PTA Root of AVL Tree (AVL樹模板+四種旋轉+指針)

clu 輸出 win 設置 node span false 講解 指定

技術分享圖片

關於AVL樹(平衡二叉搜索樹,高度為lgn)的講解,雙手呈上某大佬博客:https://www.cnblogs.com/zhuwbox/p/3636783.html

我從這題get到一個新的結構體寫法(姿勢):

typedef struct treeNode
{
    int val;
    treeNode *left;
    treeNode *right;
    int height;
}node, *tree;//node 是treeNode結構體,*tree是結構體指針

我對AVL樹的理解:

按照插入節點時旋轉的次數劃分,可以分為兩種旋轉(單旋和雙旋);繼續劃分,按照插入節點在根節點左右子樹的不同,可以具體劃分為四種旋轉:單旋轉:單左右旋(左左右旋),單右左旋(右右左旋);雙旋轉:左右左右旋,右左右左旋

例子(搬運於大佬博客):

技術分享圖片

技術分享圖片

技術分享圖片

代碼:技術分享圖片

tree rightRotation(tree t)//左左右旋
{
    tree l=t->left;
    t->left=l->right;
    l->right=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新節點高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
} tree leftRotation(tree t)//右右左旋 { tree l=t->right; t->right=l->left; l->left=t; t->height=max(height(t->left), height(t->right))+1;//跟新節點高度 l->height=max(height(l->left), height(l->right))+1; return l;//l是新的根 } tree leftRightRotation(tree t)
//左右左右旋 { t->left=leftRotation(t->left); return rightRotation(t); } tree rightLeftRotation(tree t)//右左右左旋 { t->right=rightRotation(t->right); return leftRotation(t); }

建樹函數很簡單,插入節點函數要特別提一下。如果t為NULL(樹還沒有根),那麽初始化根節點;如果t非空且val>t->val,插入右節點;如果t非空且val<t->val,插入左節點。一旦高度差值為2,進行相應的AVL旋轉(先插入節點再旋轉),最後跟新t節點高度。代碼:

tree treeCreate(tree t)
{
    int val;
    for(int i=1;i<=n;++i){
        cin>>val;
        t=nodeInsert(t, val);
    }
    return t;
}

tree nodeInsert(tree t, int val)
{
    if(!t) {t=new node;t->left=t->right=NULL;t->height=0;t->val=val;}
    else if(val>t->val) {//向節點右邊插入值
        t->right=nodeInsert(t->right, val);//先插入後旋轉
        if(height(t->right)-height(t->left)==2) {//只會出現右節點比左節點大2的情況
            if(val>t->right->val)
                t=leftRotation(t);//右右左旋
           else
                t=rightLeftRotation(t);//右左右左旋
        }
    }
    else if(val<t->val) {//向節點左邊插入
        t->left=nodeInsert(t->left, val);
        if(height(t->left)-height(t->right)==2) {
            if(val<t->left->val)
                t=rightRotation(t);//左左右旋
            else
                t=leftRightRotation(t);//左右左右旋
        }
    }
    t->height=max(height(t->left), height(t->right))+1;//更新height
    return t;
}

main函數中定義樹根t,註意將t設置為NULL,否則t作為野指針難以維護(我不會告訴你這是我調了靠近一個小時的bug

{
    cin>>n;
    tree t=NULL;//先指定t指向NULL,否則t是野指針,非常難處理
    t=treeCreate(t);
    if(t) cout<<t->val<<endl;
    return 0;
}

全部代碼:

#include <bits/stdc++.h>
using namespace std;
//AVL樹的四種旋轉情況:單旋轉:左左右旋,右右左旋,左右左右旋,右左右左旋

int n;
typedef struct treeNode
{
    int val;
    treeNode *left;
    treeNode *right;
    int height;
}node, *tree;//node 是treeNode結構體,*tree是結構體指針

int height(tree t)//計算樹的高度
{
    if(!t) return 0;//空樹
    return t->height;
}

tree rightRotation(tree t)//左左右旋
{
    tree l=t->left;
    t->left=l->right;
    l->right=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新節點高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRotation(tree t)//右右左旋
{
    tree l=t->right;
    t->right=l->left;
    l->left=t;
    t->height=max(height(t->left), height(t->right))+1;//跟新節點高度
    l->height=max(height(l->left), height(l->right))+1;
    return l;//l是新的根
}

tree leftRightRotation(tree t)//左右左右旋
{
    t->left=leftRotation(t->left);
    return rightRotation(t);
}

tree rightLeftRotation(tree t)//右左右左旋
{
    t->right=rightRotation(t->right);
    return leftRotation(t);
}

tree nodeInsert(tree t, int val)
{
    if(!t) {t=new node;t->left=t->right=NULL;t->height=0;t->val=val;}
    else if(val>t->val) {//向節點右邊插入值
        t->right=nodeInsert(t->right, val);//先插入後旋轉
        if(height(t->right)-height(t->left)==2) {//只會出現右節點比左節點大2的情況
            if(val>t->right->val)
                t=leftRotation(t);//右右左旋
           else
                t=rightLeftRotation(t);//右左右左旋
        }
    }
    else if(val<t->val) {//向節點左邊插入
        t->left=nodeInsert(t->left, val);
        if(height(t->left)-height(t->right)==2) {
            if(val<t->left->val)
                t=rightRotation(t);//左左右旋
            else
                t=leftRightRotation(t);//左右左右旋
        }
    }
    t->height=max(height(t->left), height(t->right))+1;//更新height
    return t;
}

tree treeCreate(tree t)
{
    int val;
    for(int i=1;i<=n;++i){
        cin>>val;
        t=nodeInsert(t, val);
    }
    return t;
}

void lrd(tree t)//後序遍歷 輸出調試
{
    if(t){
        lrd(t->left);
        lrd(t->right);
        cout<<t->val<<endl;
    }
}
int main()
{
    cin>>n;
    tree t=NULL;//先指定t指向NULL,否則t是野指針,非常難處理
    t=treeCreate(t);
    //lrd(t);
    if(t) cout<<t->val<<endl;
    return 0;
}

PTA Root of AVL Tree (AVL樹模板+四種旋轉+指針)