A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)
原创
©著作权归作者所有:来自51CTO博客作者nkgines的原创作品,请联系作者获取转载授权,否则将追究法律责任
写在前面
- 出现1个孩⼦为空的结点之后是否还会出现孩子结点不为空的结点,如果出现就不是完全⼆叉树
- AVL树共四种情况,发现树不平衡的结点记为A结点, A发现树不不平衡的情况有四种:
测试用例
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
ac代码
#include <iostream>
#include <vector>
#include <queue>
using namespace std;
struct node
{
int val;
struct node *left, *right;
};
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);
return rightRotate(tree);
}
node* rightLeftRotate(node *tree)
{
tree->right = rightRotate(tree->right);
return leftRotate(tree);
}
int getHeight(node *tree)
{
if(tree == NULL) return 0;
int l = getHeight(tree->left);
int r = getHeight(tree->right);
return max(l, r)+1;
}
node* inserts(node *tree, int val)
{
if(tree == NULL)
{
tree = new node();
tree->val = val;
}
else if(tree->val > val)
{
tree->left = inserts(tree->left, val);
int l = getHeight(tree->left), r = getHeight(tree->right);
if(l-r>=2)
{
if(val < tree->left->val)
tree = rightRotate(tree);
else
tree = leftRightRotate(tree);
}
}
else
{
tree->right = inserts(tree->right, val);
int l=getHeight(tree->left), r = getHeight(tree->right);
if(r-l >= 2)
{
if(val>tree->right->val)
tree = leftRotate(tree);
else
tree = rightLeftRotate(tree);
}
}
return tree;
}
int isComplete = 1, after = 0;
vector<int> levelOrder(node *tree)
{
vector<int> v;
queue<node *> queues;
queues.push(tree);
while(!queues.empty())
{
node *tmp = queues.front();
queues.pop();
v.push_back(tmp->val);
if(tmp->left != NULL)
{
if(after) isComplete = 0;
queues.push(tmp->left);
}
else
after = 1;
if(tmp->right != NULL)
{
if(after) isComplete = 0;
queues.push(tmp->right);
}
else
after = 1;
}
return v;
}
int main()
{
int n, tmp;
scanf("%d", &n);
node *tree = NULL;
for(int i=0; i<n; i++)
{
scanf("%d", &tmp);
tree = inserts(tree, tmp);
}
vector<int> v = levelOrder(tree);
for(int i=0; i<v.size(); i++)
{
if(i!=0) printf(" ");
printf("%d", v[i]);
}
printf("\n%s", isComplete ? "YES" : "NO");
return 0;
}
知识点小结
- 左右子树都是AVL树
- AVL树中任何节点的两个子树的高度最大差别为1
- 左子树和右子树高度之差(简称平衡因子)的绝对值不超过1(-1、0、1)
- 查找
- 插入
- 左旋
- 右旋
- 情况汇总
- 如果树为空,则直接返回错
- 如果树不为空:层序遍历二叉树
- 如果1个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列
- 如果遇到1个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树
- 如果遇到1个结点,左孩子不为空,右孩子为空;或左右孩子都为空;则该节点之后队列中的结点都为叶子节点;该树才是完全二叉树,否则不是完全二叉树
- 构建1个队列 依次访问二叉树的头结点
- 判断头结点不为空然后进入
- 首先将根节点入队 从根节点判断左右子节点
- 然后出队队头元素
- 队列的作用就是将二叉树按照 根 左 右的顺序接收然后出队操作
- 最终队列为空的时候 跳出循环 达到层次遍历的目的