我的PAT-ADVANCED代码仓:https://github.com/617076674/PAT-ADVANCED
原题链接:https://pintia.cn/problem-sets/994805342720868352/problems/994805351302414336
题目描述:
题目翻译:
1123 这是一棵完全AVL树吗
AVL树是一棵自平衡的二分搜索树。在AVL树中,左右子树的高度差不会超过1;任何时刻如果左右子树的高度差超过了1,自平衡操作会使得其维持左右子树高度差不超过1这个性质。下图展示了旋转规则。
现在给你一串插入序列,你需要输出由该插入顺序构成的AVL树的层序遍历,并判断该AVL树是否是一棵完全二叉树。
输入格式:
每个输入文件包含一个测试用例。在每个测试用例中,第一行有一个正整数N(<= 20)。第二行有N个不同的整数。一行中的所有数字由一个空格分隔。
输出格式:
对每个测试用例,向一棵空的AVL树中一个个插入节点。第一行打印出该AVL树的层序遍历。所有的数字由一个空格分隔,行末不得有多余空格。如果该AVL树是一棵完全二叉树,则在第二行输出“YES”;否则,在第二行输出“NO”。
输入样例1:
5
88 70 61 63 65
输出样例1:
70 63 88 61 65
YES
输入样例2:
8
88 70 61 96 120 90 65 68
输出样例2:
88 65 96 61 70 90 120 68
NO
知识点:构建AVL树、二分搜索树的层序遍历、二分搜索树的中序遍历、数组存储完全二叉树
思路一:由插入顺序构建AVL树,再层序遍历输出结果,最后由中序遍历判断是否是完全二叉树(静态数组实现)
构建AVL树的节点需要添加height变量记录树的高度,其节点结构体定义如下:
struct node{
int data;
int height;
int lchild;
int rchild;
};
需要这么几个函数:
(1)int newNode(int data):新建一个节点,新节点的高度是1,左右孩子都置为空。
(2)int getHeight(int root):获得节点高度,如果是空节点,则高度为0。
(3)int getBalanceFactor(int root):获得节点的平衡因子。
(4)void updateHeight(int root):更新节点的高度,在对节点进行左旋、右旋、插入操作后需要更新节点高度。
(5)void turnLeft(int &root):左旋操作函数。(需要传引用,因为对root变量进行了变更)
(6)void turnRight(int &root):右旋操作函数。(需要传引用,因为对root变量进行了变更)
(7)void insert(int &root, int num):插入节点函数。(需要传引用,因为对root变量进行了变更)
(8)int create():构建AVL树函数。
构建完AVL树之后,第二个问题是如何判断其是否是一棵完全二叉树?
联系堆的结构,我们很容易想到,对于完全二叉树,其层序遍历结果可以用一个数组来表示,这里我们的根节点数组下标为0。那么对于数组下标为x的节点,其左孩子节点的数组下标必然是2 * x + 1,其右孩子节点的数组下标必然是2 * x + 2。
我们只需将层序遍历的结果保存进一个数组中,对该数组进行中序遍历即可。如果中序遍历的结果是非降序排列,则说明这是一棵完全二叉树;否则,不是一棵完全二叉树。
时间复杂度和空间复杂度均是O(N)。
C++代码:
#include<iostream>
#include<vector>
#include<algorithm>
#include<queue>
using namespace std;
struct node{
int data;
int height;
int lchild;
int rchild;
};
int N;
vector<int> input;
node Node[20];
int index = 0;
vector<int> levelOrder;
vector<int> inOrder;
int newNode(int data);
int getHeight(int root);
int getBalanceFactor(int root);
void updateHeight(int root);
void turnLeft(int &root);
void turnRight(int &root);
void insert(int &root, int num);
int create();
void levelOrderTraversal(int root);
void print();
void inOrderTraversal(int root);
int main(){
cin >> N;
int num;
for(int i = 0; i < N; i++){
cin >> num;
input.push_back(num);
}
int root = create();
if(root == -1){
cout << "YES" << endl;
return 0;
}
levelOrderTraversal(root);
print();
inOrderTraversal(0);
for(int i = 0; i < inOrder.size() - 1; i++){
if(inOrder[i + 1] < inOrder[i]){
cout << "NO" << endl;
return 0;
}
}
cout << "YES" << endl;
return 0;
}
int newNode(int data){
int root = index++;
Node[root].data = data;
Node[root].height = 1;
Node[root].lchild = Node[root].rchild = -1;
return root;
}
int getHeight(int root){
if(root == -1){
return 0;
}
return Node[root].height;
}
int getBalanceFactor(int root) {
return getHeight(Node[root].lchild) - getHeight(Node[root].rchild);
}
void updateHeight(int root){
Node[root].height = max(getHeight(Node[root].lchild), getHeight(Node[root].rchild)) + 1;
}
void turnLeft(int &root) {
int temp = Node[root].rchild;
Node[root].rchild = Node[temp].lchild;
Node[temp].lchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void turnRight(int &root) {
int temp = Node[root].lchild;
Node[root].lchild = Node[temp].rchild;
Node[temp].rchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void insert(int &root, int num){
if(root == -1){
root = newNode(num);
return;
}
if(num < Node[root].data){
insert(Node[root].lchild, num);
updateHeight(root);
if(getBalanceFactor(root) == 2){
if(getBalanceFactor(Node[root].lchild) == 1){
turnRight(root);
}else if(getBalanceFactor(Node[root].lchild) == -1){
turnLeft(Node[root].lchild);
turnRight(root);
}
}
}else{
insert(Node[root].rchild, num);
updateHeight(root);
if(getBalanceFactor(root) == -2){
if(getBalanceFactor(Node[root].rchild) == -1){
turnLeft(root);
}else if(getBalanceFactor(Node[root].rchild) == 1){
turnRight(Node[root].rchild);
turnLeft(root);
}
}
}
}
int create(){
int root = -1;
for(int i = 0; i < N; i++){
insert(root, input[i]);
}
return root;
}
void levelOrderTraversal(int root){
queue<int> q;
q.push(root);
while(!q.empty()){
int now = q.front();
levelOrder.push_back(Node[now].data);
q.pop();
if(Node[now].lchild != -1){
q.push(Node[now].lchild);
}
if(Node[now].rchild != -1){
q.push(Node[now].rchild);
}
}
}
void print(){
for(int i = 0; i < levelOrder.size(); i++){
cout << levelOrder[i];
if(i != levelOrder.size() - 1){
cout << " ";
}
}
cout << endl;
}
void inOrderTraversal(int root){
if(root >= levelOrder.size()){
return;
}
inOrderTraversal(root * 2 + 1);
inOrder.push_back(levelOrder[root]);
inOrderTraversal(root * 2 + 2);
}
C++解题报告:
思路二:由插入顺序构建AVL树,再层序遍历输出结果,最后由中序遍历判断是否是完全二叉树(指针实现)
指针形式的节点结构体定义如下:
struct node{
int data;
int height;
node* lchild;
node* rchild;
};
构建AVL树的指针形式的函数如下:
需要这么几个函数:
(1)node* newNode(int data):新建一个节点,新节点的高度是1,左右孩子都置为空。
(2)int getHeight(node* root):获得节点高度,如果是空节点,则高度为0。
(3)int getBalanceFactor(node* root):获得节点的平衡因子。
(4)void updateHeight(node* root):更新节点的高度,在对节点进行左旋、右旋、插入操作后需要更新节点高度。
(5)void leftTurn(node* &root):左旋操作函数。(需要传引用,因为对root变量进行了变更)
(6)void rightTurn(node* &root):右旋操作函数。(需要传引用,因为对root变量进行了变更)
(7)void insert(node* &root, int num):插入节点函数。(需要传引用,因为对root变量进行了变更)
(8)node* create():构建AVL树函数。
时间复杂度和空间复杂度均是O(N)。
C++代码:
#include<iostream>
#include<vector>
#include<queue>
using namespace std;
struct node{
int data;
int height;
node* lchild;
node* rchild;
};
int N;
vector<int> input;
vector<int> levelOrder;
vector<int> inOrder;
node* newNode(int data);
int getHeight(node* root);
int getBalanceFactor(node* root);
void updateHeight(node* root);
void leftTurn(node* &root);
void rightTurn(node* &root);
void insert(node* &root, int num);
node* create();
void levelOrderTraversal(node* root);
void inOrderTraversal(int root);
void print();
int main(){
cin >> N;
int num;
for(int i = 0; i < N; i++){
cin >> num;
input.push_back(num);
}
node* root = create();
levelOrderTraversal(root);
print();
inOrderTraversal(0);
for(int i = 0; i < inOrder.size() - 1; i++){
if(inOrder[i + 1] < inOrder[i]){
cout << "NO" << endl;
return 0;
}
}
cout << "YES" << endl;
return 0;
}
node* newNode(int data){
node* root = new node; //此处需要new一个node
root->data = data;
root->height = 1;
root->lchild = NULL;
root->rchild = NULL;
return root;
}
int getHeight(node* root){
if(root == NULL){
return 0;
}
return root->height;
}
int getBalanceFactor(node* root){
return getHeight(root->lchild) - getHeight(root->rchild);
}
void updateHeight(node* root){
root->height = max(getHeight(root->lchild), getHeight(root->rchild)) + 1;
}
void leftTurn(node* &root){
node* temp = root->rchild;
root->rchild = temp->lchild;
temp->lchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void rightTurn(node* &root){
node* temp = root->lchild;
root->lchild = temp->rchild;
temp->rchild = root;
updateHeight(root);
updateHeight(temp);
root = temp;
}
void insert(node* &root, int num){
if(root == NULL){
root = newNode(num);
return;
}
if(num < root->data){
insert(root->lchild, num);
updateHeight(root);
if(getBalanceFactor(root) == 2){
if(getBalanceFactor(root->lchild) == 1){
rightTurn(root);
}else if(getBalanceFactor(root->lchild) == -1){
leftTurn(root->lchild);
rightTurn(root);
}
}
}else{
insert(root->rchild, num);
updateHeight(root);
if(getBalanceFactor(root) == -2){
if(getBalanceFactor(root->rchild) == -1){
leftTurn(root);
}else if(getBalanceFactor(root->rchild) == 1){
rightTurn(root->rchild);
leftTurn(root);
}
}
}
}
node* create(){
node* root = NULL;
for(int i = 0; i < N; i++){
insert(root, input[i]);
}
return root;
}
void levelOrderTraversal(node* root){
queue<node*> q;
q.push(root);
while(!q.empty()){
node* now = q.front();
levelOrder.push_back(now->data);
q.pop();
if(now->lchild != NULL){
q.push(now->lchild);
}
if(now->rchild != NULL){
q.push(now->rchild);
}
}
}
void print(){
for(int i = 0; i < levelOrder.size(); i++){
cout << levelOrder[i];
if(i != levelOrder.size() - 1){
cout << " ";
}
}
cout << endl;
}
void inOrderTraversal(int root){
if(root >= N){
return;
}
inOrderTraversal(root * 2 + 1);
inOrder.push_back(levelOrder[root]);
inOrderTraversal(root * 2 + 2);
}
C++解题报告: