PAT-ADVANCED1123——Is It a Complete AVL Tree

我的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++解题报告:

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值