PAT甲级——1123 Is It a Complete AVL Tree (完全AVL树的判断)

嫌排版乱的话可以移步我的CSDN:https://blog.csdn.net/weixin_44385565/article/details/89390802

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.jpg F2.jpg
F3.jpg F4.jpg

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

题目大意:给出N个数据,建立AVL树,并判断其是否为完全二叉树。

思路:题目言简意赅,就两个核心操作:建立AVL树、判断是否为完全二叉树~~

AVL树的建立过程详见我之前的文章:AVL树(自平衡二叉查找树)

因为AVL树本身的性质已经保证了左右子树的高度差≤1,所以之后判断完全二叉树主要有两个条件:1、对于每个节点,左子树高度≥右子树高度;2、层序遍历遇到一个节点,它有左孩子但没有右孩子时标记一下,在它之后进入队列的节点都为叶子节点,这棵AVL树为完全二叉树。

  1 #include <iostream>
  2 #include <queue>
  3 #define ElementType int
  4 using namespace std;
  5 typedef struct node *AVLTree;
  6 struct node {
  7     ElementType key;
  8     int Height = 0;
  9     AVLTree left = NULL, right = NULL;
 10 };
 11 bool flag = true;
 12 int Height(AVLTree tree);//求树的高度
 13 ElementType Max(ElementType a, ElementType b);
 14 AVLTree insert(AVLTree tree, ElementType &key);//在AVLTree中插入节点
 15 AVLTree LL_Rotation(AVLTree tree);//LL旋转
 16 AVLTree RR_Rotation(AVLTree tree);//RR旋转
 17 AVLTree LR_Rotation(AVLTree tree);//LR旋转
 18 AVLTree RL_Rotation(AVLTree tree);//RL旋转
 19 void levelTraversal(AVLTree tree);//层序遍历
 20  
 21 int main()
 22 {
 23     int N;
 24     ElementType key;
 25     AVLTree tree = NULL;
 26     scanf("%d", &N);
 27     for (int i = 0; i < N; i++) {
 28         cin >> key;
 29         tree = insert(tree, key);
 30     }
 31     levelTraversal(tree);
 32     if (flag)
 33         printf("YES\n");
 34     else
 35         printf("NO\n");
 36  
 37 }
 38  
 39 AVLTree insert(AVLTree tree, ElementType &key) {
 40     if (tree == NULL) {
 41         tree = new node();
 42         tree->key = key;
 43     }
 44     else if (key < tree->key) {
 45         tree->left = insert(tree->left, key);//key小于当前节点的值时继续往其左子树递归地插入
 46         if (Height(tree->left) - Height(tree->right) >= 2) {//左子树与右子树的高度差达到2的时候就要对当前节点进行旋转,这里由于是递归地执行,保证了平衡因子达到2的节点是最接近插入点的
 47             if (key < tree->left->key)
 48                 tree = LL_Rotation(tree);
 49             else
 50                 tree = LR_Rotation(tree);
 51         }
 52     }
 53     else {
 54         tree->right = insert(tree->right, key);
 55         if (Height(tree->right) - Height(tree->left) >= 2) {
 56             if (key > tree->right->key)
 57                 tree = RR_Rotation(tree);
 58             else
 59                 tree = RL_Rotation(tree);
 60         }
 61     }
 62     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;//当前节点的高度为其最大子树的高度+1
 63     return tree;
 64 }
 65  
 66 AVLTree LR_Rotation(AVLTree tree) {
 67     tree->left = RR_Rotation(tree->left);
 68     return LL_Rotation(tree);
 69 }
 70  
 71 AVLTree RL_Rotation(AVLTree tree) {
 72     tree->right = LL_Rotation(tree->right);
 73     return RR_Rotation(tree);
 74 }
 75  
 76 AVLTree RR_Rotation(AVLTree tree) {
 77     AVLTree tree2 = tree->right;
 78     tree->right = tree2->left;
 79     tree2->left = tree;
 80     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
 81     tree2->Height = Max(Height(tree2->right), tree->Height) + 1;
 82     return tree2;
 83 }
 84  
 85 AVLTree LL_Rotation(AVLTree tree) {
 86     AVLTree tree2 = tree->left;
 87     tree->left = tree2->right;
 88     tree2->right = tree;
 89     tree->Height = Max(Height(tree->left), Height(tree->right)) + 1;
 90     tree2->Height = Max(Height(tree->left), tree->Height) + 1;
 91     return tree2;
 92 }
 93  
 94 int Height(AVLTree tree) {
 95     if (tree == NULL)
 96         return 0;
 97     return tree->Height;
 98 }
 99  
100 ElementType Max(ElementType a, ElementType b) {
101     return a > b ? a : b;
102 }
103  
104 void levelTraversal(AVLTree tree)
105 {
106     bool flag2 = false;
107     AVLTree t = NULL;
108     queue <AVLTree> Q;
109     Q.push(tree);
110     while (!Q.empty()) {
111         t = Q.front();
112         Q.pop();
113         cout << t->key;
114         if (flag2 && Height(t) != 1) //高度为1的节点就是叶子节点
115             flag = false;
116         if (Height(t->left) < Height(t->right)) //AVL树保证了每个节点的左右子树高度差小于等于1,只要左子树高度小于右子树,这课AVL树就不是完全二叉树
117             flag = false;
118         if (t->left != NULL && t->right == NULL) //遇到一个节点,有左孩子但没有右孩子,标记一下,它之后的存入队列中的节点都为叶子节点时这棵AVL树才是完全二叉树
119             flag2 = true;
120         if (t->left != NULL)
121             Q.push(t->left);
122         if (t->right != NULL)
123             Q.push(t->right);
124         if (!Q.empty())
125             printf(" ");
126     }
127     printf("\n");
128 }

猜你喜欢

转载自www.cnblogs.com/yinhao-ing/p/10736535.html