PAT.A.1123 Is It a Complete AVL Tree (30 分)

编辑:谯胜平      分类:程序与算法      标签:完全二叉树      发布时间:2019-08-30      浏览次数:668

题目链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805351302414336

Question introduction:    

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.

F1.jpgF2.jpg
F3.jpgF4.jpg

Input Specification:

Nowgiven 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.

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

1、分析

题目的意思是给定二叉排序树的插入序列,要求建立一棵平衡二叉树并输出层次遍历,同时说出该树是否是完全二叉树。我们大致需要做一下几个工作:

  • 根据输入序列建立平衡二叉树;

  • 层次遍历;

  • 判断是否是完全二叉树;

这里的前两个步骤都是常见的操作,只需要尽量把代码写正确,精准即可,我的代码主要参照《算法笔记》上的。

下面说说判断是否是完全二叉树的判断方法。如下图,使用层次遍历整个二叉树,如果遇到某个节点的左孩子节点或者右孩子节点为空,则开启叶子结点阶段,此后如果还遇到孩子节点不为空的节点,则该二叉树不是完全二叉树。

ubang_image_20190830898149.png

2、代码

#include<stdio.h>
#include<vector>
#include<algorithm>
#include<queue> 
using namespace std;
struct node{
    node *left, *right;
    int data;
    int height;
};

//新建节点 
node* newNode(int data){
    node *root = new node;
    root -> left = root -> right = NULL;
    root -> data = data;
    root -> height = 1;
    return root;
}

//获取高度 
int getHeight(node* root){
    if(root == NULL) return 0;
    return root -> height;
}

//获取平衡银子 
int getBalanceFactor(node* root){
    //平衡因子为左子树高度-右子树高度 
    return getHeight(root -> left) - getHeight(root -> right);
}

//更新树高度 
void updateHeight(node* &root){
    //节点高度为左子树和右子树高度的最大值+1
    root -> height = max(getHeight(root -> left), getHeight(root -> right)) + 1;
}

//左旋 
void L(node* &root){
    node* temp = root -> right;
    root -> right = temp -> left;
    temp -> left = root;
    //更新高度
    updateHeight(root);
    updateHeight(temp);
    root = temp;
}

//右旋 
void R(node* &root){
    node* temp = root -> left;
    root -> left = temp -> right;
    temp -> right = root;
    updateHeight(root);
    updateHeight(temp);
    root = temp;
}

//插入节点 
void insert(node* &root, int data){
    if(root == NULL){
        root = newNode(data);
        return;
    }
    if(data < root -> data){
        //插入左子树
        insert(root -> left, data);
        //更新树高 
        updateHeight(root);
        //如果树平衡因子==2则需要调整
        if(getBalanceFactor(root) == 2){
            if(getBalanceFactor(root -> left) == 1){
                //右旋
                R(root);
            }else if(getBalanceFactor(root -> left) == -1){
                //先左旋后右旋
                L(root -> left);
                R(root);
            }
        }
    }else{
        insert(root -> right, data);
        updateHeight(root);
        if(getBalanceFactor(root) == -2){
            if(getBalanceFactor(root -> right) == 1){
                R(root -> right);
                L(root);
            }else if(getBalanceFactor(root -> right) == -1){
                L(root);
            }
        }
    }
}

//建立平衡二叉树 
node *create(int data[], int n){
    node* root = NULL;
    for(int i = 0; i < n; i++){
        insert(root, data[i]);
    }
    return root;
}

//层次遍历 
void levelOrder(node* root, vector<int> &level){
    queue<node*> q;
    q.push(root);
    while(!q.empty()){
        node* temp = q.front();
        level.push_back(temp -> data);
        q.pop();
        if(temp -> left != NULL) q.push(temp -> left);
        if(temp -> right != NULL) q.push(temp -> right);
    }
}

//判断是否是完全二叉树 
bool isCompleteBinaryTree(node* root){
    if(root == NULL) return false;
    queue<node*> q;
    q.push(root);
    bool leaf = false;
    while(!q.empty()){
        node* temp = q.front();
        q.pop();
        if(leaf){
            //如果叶子阶段还存在左右子树不为空则返回false 
            if(temp -> left != NULL || temp -> right != NULL){
                return false;
            }
        }else{
            if(temp -> left != NULL && temp -> right != NULL){
                q.push(temp -> left);
                q.push(temp -> right);
            }else if(temp -> left == NULL && temp -> right != NULL){
                return false;
            }else{
                leaf = true;    //开启leaf标志 
                if(temp -> left != NULL) q.push(temp -> left);
            }
        }   
    }
    return true;
}

int main(){
    int n, data[20];
    scanf("%d", &n);
    for(int i = 0; i < n; i++){
        scanf("%d", &data[i]);
    }
    node *root = create(data, n);
    vector<int> ans;
    levelOrder(root, ans);
    for(int i = 0; i < ans.size(); i++){
        printf("%d", ans[i]);
        if(i < ans.size() - 1) printf(" ");
    }
    printf("\n");
    if(isCompleteBinaryTree(root)){
        printf("YES\n");
    }else printf("NO\n");
    return 0;
}




看不清?换一个