题目链接https://pintia.cn/problem-sets/994805342720868352/problems/994805351302414336
题目大意:给出N
个数字,建AVL树。然后输出层序遍历。最后判断是否是完全二叉树。
正常的左旋右旋左右旋右左旋代码书上都有,不赘述了。层序遍历用个queue就行。在层序遍历时判断是否是完全二叉树,我们给每个结点加一个属性pos
,根的pos==1
,那么左儿子的pos
等于父亲的2倍,右儿子的pos
等于父亲的两倍+1。如果一棵树是完全二叉树,那么其pos
应该刚好为从1
到N
,出现大于N
的pos
时,直接置isComp
为false
就行。
void lvlOrder(Node* root) {
queue<Node*> q;
q.push(root);
q.front()->pos = 1;
while (!q.empty()) {
if (q.front()->left) {
q.push(q.front()->left);
q.front()->left->pos = q.front()->pos * 2;
}
if (q.front()->right) {
q.push(q.front()->right);
q.front()->right->pos = q.front()->pos * 2 + 1;
}
if (q.front() == root)
printf("%d", q.front()->val);
else
printf(" %d", q.front()->val);
if (q.front()->pos > N)
isComp = false;
q.pop();
}
printf("\n");
}
一开始做的时候,测试点2、3一直过不去,感觉也没问题了。检查半天才发现,结点的高度(height)是可能变化的,而我一开始仅在插入时计算其高度,并将高度作为结点的一个属性了。实际上由于AVL树会调整结构,所以高度也有可能变化,每次需要高度时应该用函数getHeight()
重新计算才行。
完整代码
#include <iostream>
#include <cstdio>
#include <cmath>
#include <vector>
#include <algorithm>
#include <queue>
#include <map>
#include <set>
using namespace std;
class Node{
public:
int val, pos;
Node *left, *right;
Node() {
left = right = nullptr;
}
Node(int num) {
val = num;
left = right = nullptr;
}
};
int N;
Node* tree = nullptr;
bool isComp = true;
int getHeight(Node* node) {
if (node == nullptr)
return -1;
else
return max(getHeight(node->left), getHeight(node->right)) + 1;
}
Node* leftSingleRot(Node* root) {
Node* mid = root->left;
root->left = mid->right;
mid->right = root;
return mid;
}
Node* rightSingleRot(Node* root) {
Node* mid = root->right;
root->right = mid->left;
mid->left = root;
return mid;
}
Node* leftDoubleRot(Node* root) {
root->left = rightSingleRot(root->left);
return leftSingleRot(root);
}
Node* rightDoubleRot(Node* root) {
root->right = leftSingleRot(root->right);
return rightSingleRot(root);
}
Node* insert(Node* node, int num) {
if (node == nullptr) {
node = new Node(num);
return node;
}
if (num > node->val) {
node->right = insert(node->right, num);
if (getHeight(node->right) - getHeight(node->left) == 2) {
if (num > node->right->val)
node = rightSingleRot(node);
else
node = rightDoubleRot(node);
}
}
else {
node->left = insert(node->left, num);
if (getHeight(node->left) - getHeight(node->right) == 2) {
if (num < node->left->val)
node = leftSingleRot(node);
else
node = leftDoubleRot(node);
}
}
return node;
}
void lvlOrder(Node* root) {
queue<Node*> q;
q.push(root);
q.front()->pos = 1;
while (!q.empty()) {
if (q.front()->left) {
q.push(q.front()->left);
q.front()->left->pos = q.front()->pos * 2;
}
if (q.front()->right) {
q.push(q.front()->right);
q.front()->right->pos = q.front()->pos * 2 + 1;
}
if (q.front() == root)
printf("%d", q.front()->val);
else
printf(" %d", q.front()->val);
if (q.front()->pos > N)
isComp = false;
q.pop();
}
printf("\n");
}
int main() {
scanf("%d", &N);
for (int i = 0; i < N; i++) {
int num;
scanf("%d", &num);
tree = insert(tree, num);
}
lvlOrder(tree);
if (isComp)
printf("YES");
else
printf("NO");
return 0;
}