写在前面

  • 思路分析
  • 判断是不是完全二叉树
  • 出现1个孩⼦为空的结点之后是否还会出现孩子结点不为空的结点,如果出现就不是完全⼆叉树
  • AVL树共四种情况,发现树不平衡的结点记为A结点, A发现树不不平衡的情况有四种:
  • 知识盲点,学习ing
  • 难度较大,代码量较大

测试用例

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树
  • AVL树中任何节点的两个子树的高度最大差别为1
  • 左子树和右子树高度之差(简称平衡因子)的绝对值不超过1(-1、0、1)
  • 查找
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_A1123

  • 插入
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_AVL树_02

  • 左旋
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_A1123_03

  • 右旋
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_层次遍历_04

  • 情况汇总
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_层次遍历_05

  • 如果树为空,则直接返回错
  • 如果树不为空:层序遍历二叉树
  • 如果1个结点左右孩子都不为空,则pop该节点,将其左右孩子入队列
  • 如果遇到1个结点,左孩子为空,右孩子不为空,则该树一定不是完全二叉树
  • 如果遇到1个结点,左孩子不为空,右孩子为空;或左右孩子都为空;则该节点之后队列中的结点都为叶子节点;该树才是完全二叉树,否则不是完全二叉树
  • 构建1个队列 依次访问二叉树的头结点
  • 判断头结点不为空然后进入
  • 首先将根节点入队 从根节点判断左右子节点
  • 然后出队队头元素
  • 队列的作用就是将二叉树按照 根 左 右的顺序接收然后出队操作
  • 最终队列为空的时候 跳出循环 达到层次遍历的目的
  • A1123 Is It a Complete AVL Tree (30 分| AVL树| 完全二叉树| 层次遍历,附详细注释,逻辑分析)_层次遍历_06