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