1123. Is It a Complete AVL Tree (30)
时间限制: 400 ms
内存限制: 65536 kB
代码长度限制: 16000 B
判题程序:Standard
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 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 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.
Examples
>| Input| | ------------- | | 5
88 70 61 63 65 | | Output | | 70 63 88 61 65
YES |
>| ------------- | >| Input| | 8
88 70 61 96 120 90 65 68| | Output | | 88 65 96 61 70 90 120 68
NO| Notes
作者 CHEN, Yue
下面程序的AVL树是用平衡因子实现的,平衡处理是独立的,再插入操作完成后进行,这样的写法可能更清晰,易于理解。
判断树是否为完全二叉树的做法是,用一个存储节点指针的queue对树进行层次遍历,从根节点开始,先将其指针加入queue,不断将queue的队首元素的左右节点指针(空指针也加入)加入queue后将队首元素移出,直到queue空为止。在遍历的过程中,queue队首元素第一次为空指针时,如果已经将所有节点遍历完(计数即可),就说明该树为完全二叉树。
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
#include <functional>
#include <string>
#include <cstring>
#include <queue>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <sstream>
#include <iomanip>
using namespace std;
#define IOS ios_base::sync_with_stdio(false)
#define TIE std::cin.tie(0)
#define MIN2(a,b) (a<b?a:b)
#define MIN3(a,b) (a<b?(a<c?a:c):(b<c?b:c))
#define MAX2(a,b) (a>b?a:b)
#define MAX3(a,b,c) (a>b?(a>c?a:c):(b>c?b:c))
typedef long long LL;
typedef unsigned long long ULL;
const int INF = 0x3f3f3f3f;
const double PI = 4.0*atan(1.0);
const double eps = 1e-6;
int n, x;
struct AVLTree{
struct AVLTreeNode{
int data;
int balanceFactor;//平衡因子
AVLTreeNode * left = NULL;
AVLTreeNode * right = NULL;
AVLTreeNode(){}
AVLTreeNode(int item) :data(item){}
};
typedef AVLTreeNode * AVLTreeNodePointer;
void insert(int item);
void adj();
int adjAux(AVLTreeNodePointer & subtreeRoot, int h);
void leftSingleRotation(AVLTreeNodePointer & subtreeRoot);
void rightSingleRotation(AVLTreeNodePointer & subtreeRoot);
void leftDoubleRotation(AVLTreeNodePointer & subtreeRoot);
void rightDoubleRotation(AVLTreeNodePointer & subtreeRoot);
void levelorder(AVLTreeNodePointer subtreeRoot) const;
AVLTreeNodePointer myRoot = NULL;
};
void AVLTree::insert(int item)
{
AVLTreeNodePointer locptr = myRoot; //查找指针
AVLTreeNodePointer parent = 0;
bool found = false; //表示item是否已存在于树中
while (!found && locptr != 0)
{
parent = locptr;
if (item < locptr->data) //下降到左子树
locptr = locptr->left;
else if (locptr->data < item) //下降到右子树
locptr = locptr->right;
else
found = true; //item被找到
}
if (!found) //item未被找到
{
//创建包含item的节点
locptr = new AVLTreeNode(item);
if (parent == 0) //当前树为空
myRoot = locptr;
else if (item < parent->data) //作为父亲节点的左孩子插入
parent->left = locptr;
else
parent->right = locptr; //作为父亲节点的右孩子插入
}
else
;//item已存在
}
void AVLTree::adj()
{
adjAux(myRoot, 1);
}
int AVLTree::adjAux(AVLTreeNodePointer & subtreeRoot, int h)
{
//参数height为节点的高度,设定根节点的高度为1,自顶向下逐层的高度依次加1
int leftHeight = 0, rightHeight = 0;
if (subtreeRoot != NULL)
{
h++; //高度增加1
leftHeight = adjAux(subtreeRoot->left, h); //左子树相对根节点的高度
rightHeight = adjAux(subtreeRoot->right, h); //右子树相对根节点的高度
subtreeRoot->balanceFactor = leftHeight - rightHeight; //计算平衡因子
if (subtreeRoot->balanceFactor == 2) //左子树高
{
if (subtreeRoot->left->balanceFactor == 1) //右单旋
rightSingleRotation(subtreeRoot);
else if (subtreeRoot->left->balanceFactor == -1) //右双旋
rightDoubleRotation(subtreeRoot);
return adjAux(subtreeRoot, h - 1); //旋转调整后重新计算平衡因子
}
else if (subtreeRoot->balanceFactor == -2) //右子树高
{
if (subtreeRoot->right->balanceFactor == -1) //左单旋
leftSingleRotation(subtreeRoot);
else if (subtreeRoot->right->balanceFactor == 1) //左双旋
leftDoubleRotation(subtreeRoot);
return adjAux(subtreeRoot, h - 1); //旋转调整后重新计算平衡因子
}
else //不需调整,返回左子树和右子树树高的最大值
{ //即为父亲节点的高度
return max(leftHeight, rightHeight);
}
}
else
return h; //节点为空
}
void AVLTree::leftSingleRotation(AVLTreeNodePointer & subtreeRoot)
{
AVLTreeNodePointer rightTree = subtreeRoot->right;
subtreeRoot->right = rightTree->left;
rightTree->left = subtreeRoot;
subtreeRoot = rightTree;
}
void AVLTree::rightSingleRotation(AVLTreeNodePointer & subtreeRoot)
{
AVLTreeNodePointer leftTree = subtreeRoot->left;
subtreeRoot->left = leftTree->right;
leftTree->right = subtreeRoot;
subtreeRoot = leftTree;
}
void AVLTree::leftDoubleRotation(AVLTreeNodePointer & subtreeRoot)
{
AVLTreeNodePointer rightTree = subtreeRoot->right,
child = rightTree->left;
//右旋
rightTree->left = child->right;
child->right = rightTree;
subtreeRoot->right = child;
//左旋
subtreeRoot->right = child->left;
child->left = subtreeRoot;
subtreeRoot = child;
}
void AVLTree::rightDoubleRotation(AVLTreeNodePointer & subtreeRoot)
{
AVLTreeNodePointer leftTree = subtreeRoot->left,
child = leftTree->right;
//左旋
leftTree->right = child->left;
child->left = leftTree;
subtreeRoot->left = child;
//右旋
subtreeRoot->left = child->right;
child->right = subtreeRoot;
subtreeRoot = child;
}
void AVLTree::levelorder(AVLTreeNodePointer subtreeRoot) const
{
queue<AVLTreeNodePointer> que;
que.push(myRoot);
bool first = true, nullfir=true;
bool cmp = false;
int cnt = 0;
while (!que.empty()){
AVLTreeNodePointer ptr = que.front();
que.pop();
if (ptr == NULL){
if (nullfir){
nullfir = false;
if (cnt == n)
cmp = true;
}
continue;
}
cnt++;
if(first) first = false;
else printf(" ");
printf("%d", ptr->data);
que.push(ptr->left);
que.push(ptr->right);
}
printf("
%s
", cmp ? "YES" : "NO");
}
int main()
{
AVLTree tree;
scanf("%d", &n);
for (int i = 0; i < n; i++)
{
scanf("%d", &x);
tree.insert(x);
tree.adj();
}
tree.levelorder(tree.myRoot);
//system("pause");
}
//system("pause");