1. 程式人生 > >PAT-ADVANCED1123——Is It a Complete AVL Tree

PAT-ADVANCED1123——Is It a Complete AVL Tree

題目描述:

題目翻譯:

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++解題報告: