PAT-ADVANCED1020——Tree Traversals
阿新 • • 發佈:2018-11-06
我的PAT-ADVANCED程式碼倉:https://github.com/617076674/PAT-ADVANCED
原題連結:https://pintia.cn/problem-sets/994805342720868352/problems/994805485033603072
題目描述:
題目翻譯:
1020 樹的遍歷
假設二叉樹節點上的所有值都是不同的正整數。給你一棵二叉樹的後序遍歷和中序遍歷結果,你需要給出其層序遍歷結果。
輸入格式:
每個輸入檔案包含一個測試用例。在每個測試用例中,第一行給出一個正整數N(<= 30),代表二叉樹的節點個數。第二行給出後序遍歷結果,第三行給出中序遍歷結果。一行中所有的數字由一個空格分隔。
輸出格式:
對每個測試用例,在一行中打印出這課二叉樹的層序遍歷結果。一行中所有的數字必須以一個空格分隔,行末不得有多餘空格。
輸入樣例:
7
2 3 1 5 7 6 4
1 2 3 4 5 6 7
輸出樣例:
4 1 6 3 5 7 2
知識點:二叉樹的後序遍歷、層序遍歷、中序遍歷
思路一:指標實現
中序遍歷可以與前序遍歷、後序遍歷、層序遍歷中的任意一來構建一棵唯一的二叉樹,而後三者兩兩搭配或是三個一起上都無法構建唯一的二叉樹。原因是前序、後序、層序均是提供根節點,作用是相同的,都必須由中序遍歷來區分出左右子樹。
時間複雜度與這課二叉樹的構成有關,最壞情況是退化成一個連結串列,是O(N)的複雜度,最好情況是一顆平衡二叉樹,是O(logN)的複雜度。空間複雜度是O(N)。
C++程式碼:
#include<iostream> #include<queue> using namespace std; struct node { int data; node* lchild; node* rchild; }; int N; //二叉樹的節點個數 int postOrder[31]; //後序遍歷陣列 int inOrder[31]; //中序遍歷陣列 int levelOrder[31]; int index = 0; /* 當前後序序列區間為[leftPost, rightPost],中序序列區間為[leftIn, rightIn],返回根節點地址 */ node* create(int leftPost, int rightPost, int leftIn, int rightIn); /* 層序遍歷二叉樹 */ void levelTraversal(node* root); int main(){ cin >> N; for(int i = 0; i < N; i++){ cin >> postOrder[i]; } for(int i = 0; i < N; i++){ cin >> inOrder[i]; } node* root = create(0, N - 1, 0, N - 1); //這裡右邊界是N - 1,而不是N,在函式的定義中,左右邊界都是閉區間 levelTraversal(root); for(int i = 0; i < N; i++){ cout << levelOrder[i]; if(i != N - 1){ cout << " "; } } cout << endl; return 0; } node* create(int leftPost, int rightPost, int leftIn, int rightIn){ if(leftPost > rightPost){ return NULL; //後序序列的長度小於等於0時,直接返回 } node* root = new node; root->data = postOrder[rightPost]; //新節點的資料域為根結點的值 int k; for(k = leftIn; k <= rightIn; k++){ if(inOrder[k] == postOrder[rightPost]){ break; } } int numLeft = k - leftIn; //左子樹的節點個數 root->lchild = create(leftPost, leftPost + numLeft - 1, leftIn, k - 1); root->rchild = create(leftPost + numLeft, rightPost - 1, k + 1, rightIn); return root; } void levelTraversal(node* root){ if(root == NULL){ return; } queue<node*> q; q.push(root); while(!q.empty()){ node* now = q.front(); q.pop(); levelOrder[index++] = now->data; if(now->lchild != NULL){ q.push(now->lchild); } if(now->rchild != NULL){ q.push(now->rchild); } } }
C++解題報告:
思路二:靜態陣列實現
建立一個大小為節點上限個數的node型陣列,所有動態生成的節點都直接使用陣列中的節點,所有對指標的操作都改為對陣列下標的訪問。
C++程式碼:
#include<iostream>
#include<queue>
using namespace std;
struct node {
int data;
int lchild;
int rchild;
};
int N; //二叉樹的節點個數
int postOrder[31]; //後序遍歷陣列
int inOrder[31]; //中序遍歷陣列
int levelOrder[31]; //層序遍歷陣列
node Node[31];
int index = 0;
int resultIndex = 0;
int create(int leftPost, int rightPost, int leftIn, int rightIn);
void levelTraversal(int root);
int main(){
cin >> N;
for(int i = 0; i < N; i++){
cin >> postOrder[i];
}
for(int i = 0; i < N; i++){
cin >> inOrder[i];
}
int root = create(0, N - 1, 0, N - 1);
levelTraversal(root);
for(int i = 0; i < N; i++){
cout << levelOrder[i];
if(i != N - 1){
cout << " ";
}
}
cout << endl;
return 0;
}
int create(int leftPost, int rightPost, int leftIn, int rightIn){
if(leftPost > rightPost){
return -1;
}
int root = index++;
Node[root].data = postOrder[rightPost];
int k;
for(k = leftIn; k <= rightIn; k++){
if(inOrder[k] == postOrder[rightPost]){
break;
}
}
int numLeft = k - leftIn;
Node[root].lchild = create(leftPost, leftPost + numLeft - 1, leftIn, k - 1);
Node[root].rchild = create(leftPost + numLeft, rightPost - 1, k + 1, rightIn);
return root ;
}
void levelTraversal(int root){
if(root == -1){
return;
}
queue<int> q;
q.push(root);
while(!q.empty()){
int now = q.front();
q.pop();
levelOrder[resultIndex++] = Node[now].data;
if(Node[now].lchild != -1){
q.push(Node[now].lchild);
}
if(Node[now].rchild != -1){
q.push(Node[now].rchild);
}
}
}
C++解題報告: