1. 程式人生 > >1123. Is It a Complete AVL Tree(AVL樹旋轉、判斷完全二叉樹)

1123. Is It a Complete AVL Tree(AVL樹旋轉、判斷完全二叉樹)

Is It a Complete AVL Tree (30)
An AVL tree is a self-balancing binary search tree. In an AVL tree, the heights of the two child subtrees of any node differ by at most one; if at any time they differ by more than one, rebalancing is done to restore this property. Figures 1-4 illustrate the rotation rules.
這裡寫圖片描述


Now given a sequence of insertions, you are supposed to output the level-order traversal sequence of the resulting AVL tree, and to tell if it is a complete binary tree.

Input Specification:

Each input file contains one test case. For each case, the first line contains a positive integer N (<= 20). Then N distinct integer keys are given in the next line. All the numbers in a line are separated by a space.

Output Specification:

For each test case, insert the keys one by one into an initially empty AVL tree. Then first print in a line the level-order traversal sequence of the resulting AVL tree. All the numbers in a line must be separated by a space, and there must be no extra space at the end of the line. Then in the next line, print “YES” if the tree is complete, or “NO” if not.

Sample Input 1:
5
88 70 61 63 65
Sample Output 1:
70 63 88 61 65
YES
Sample Input 2:
8
88 70 61 96 120 90 65 68
Sample Output 2:
88 65 96 61 70 90 120 68
NO

題目說明:根據AVL樹的插入規則,輸入一段數字,根據輸入的數字構建 AVL樹。然後,根據層序遍歷輸出對應的數字,之後再判斷這棵AVL樹是否是完全二叉樹。
分析要點:這道題首先要解決的問題是引起AVL樹不平衡的插入的四種情況(設結點A為不平衡結點):
1.新插入的結點在A的左子樹的左子樹。
2.新插入的結點在A的左子樹的右子樹。
3.新插入的結點在A的右子樹的左子樹。
4.新插入的結點在A的右子樹的右子樹。
如何判斷出現不平衡呢?其實也非常簡單。對於一個結點來說,一個結點的左子樹高度和右子樹高度相差>=2,說明出現了不平衡。需要進行旋轉。
旋轉的規則也簡單:情況1.右旋。2.對A的左子樹進行左旋(接著會出現情況1),接著對A右旋。3.對A的右子樹進行右旋(接著會出現情況4),接著去A左旋。4.左旋。
最後,如何判斷是否為完全二叉樹。這個也簡單,回想完全二叉樹的定義:葉結點與葉結點的高度差不能超過2。並且,缺的部分必須在右邊。所以,只要從左到右的層序遍歷,一旦出現了葉結點,就不能再出現非葉結點了。

如何左旋和右旋呢?我覺得程式碼更清楚,程式碼如下:

#include<iostream>
#include<cstdio>
#include<vector>
#include<queue>
using namespace std;

int isComplete=1;int after=0;


struct node
{
    int val;
    node* left;
    node* right;
    node(int a):val(a),left(NULL),right(NULL){}
};

node* leftrotate(node* tree)
{
    node* tmp=tree->right;
    tree->right=tmp->left;
    tmp->left=tree;
    return tmp;
}

node* rightrotate(node* tree)
{
    node* tmp=tree->left;
    tree->left=tmp->right;
    tmp->right=tree;
    return tmp;
}

node* leftRightrotate(node* tree)
{
    tree->left=leftrotate(tree->left);
    tree=rightrotate(tree);
    return tree;
}

node* rightLeftrotate(node* tree)
{
    tree->right=rightrotate(tree->right);
    tree=leftrotate(tree);
    return tree;
}

int getHeight(node* tree)
{
    if(tree==NULL)
        return 0;
    else
    {
        int l=getHeight(tree->left);
        int r=getHeight(tree->right);
        return l>r? l+1:r+1;
    }
}

node* insert(node* root,int val)
{
    if(root==NULL)
    {
        node* tree=new node(val);
        return tree;
    }
    else
    {
        if(val>(root->val))
        {
            root->right=insert(root->right,val);
            int l=getHeight(root->left);
            int r=getHeight(root->right);
            if(r-l>=2)
            {
                if(val<(root->right->val))
                    root=rightLeftrotate(root);
                else
                    root=leftrotate(root);
            }
        }
        else
        {
            root->left=insert(root->left,val);
            int l=getHeight(root->left);
            int r=getHeight(root->right);
            if(l-r>=2)
            {
                if(val>(root->left->val))
                    root=leftRightrotate(root);
                else
                    root=rightrotate(root);
            }
        }
    }
    return root;
}


vector<int> printtree(node* root)
{
    vector<int> res;
    queue<node*> q;
    q.push(root);
    while(!q.empty())
    {
        node* tmp=q.front();
        q.pop();
        res.push_back(tmp->val);
        //滿二叉樹的定義是一旦一個結點的左兒子有結點,後面的所有結點必須全為葉子結點
        //所以出現左邊沒結點,右邊有結點也不為完全樹
        //故一旦從左邊開始出現葉子結點,後面都必須是葉子結點
        if(tmp->left!=NULL)
        {
            if(after)
            {
                isComplete=0;
            }
            q.push(tmp->left);
        }
        else
        {
            after=1;
        }
        if(tmp->right!=NULL)
        {
            if(after)
            {
                isComplete=0;
            }
            q.push(tmp->right);
        }
        else
        {
            after=1;
        }
    }
    return res;
}



int main()
{
    int k;
    scanf("%d",&k);
    node* tree;
    for(int i=0;i<k;++i)
    {
        int tmp;
        scanf("%d",&tmp);
        tree=insert(tree,tmp);
    }
    vector<int> res=printtree(tree);
    for(int i=0;i<res.size();++i)
    {
        if(i==0)
            printf("%d",res[i]);
        else
            printf(" %d",res[i]);
    }
    printf("\n");
    if(isComplete)
        printf("YES");
    else
        printf("NO");
    return 0;
}