/**
* 問題描述:
* 根據一顆二叉樹的前序和中序遍歷結果,重構這顆二叉樹並輸出後序遍歷結果
*/
#include <iostream>
using namespace std;
typedef struct node {
int value;
struct node *left;
struct node *right;
}NODE;
NODE *root;
//節點分配函式
NODE *malloc_NODE(int value){
NODE *p = NULL;
p = (NODE *)malloc(sizeof(NODE));
p->value = value;
p->right = NULL;
p->left = NULL;
return p;
}
/**
* 每次遞迴根節點已經建立好,我們的任務就是遞迴建立左子樹和右子樹
* 從圖中可以看到:
* 左子樹的前序和中序的起始指標很容易找到,但是右子樹的
* 前序和中序的起始指標需要知道左子樹的長度才行。
* 此外我們還需要維護一個子樹的長度tLen,以便知道當前遞迴是否應該結束。
*/
void rebuild_tree(NODE *root, //當前子樹根節點
int *pre, //當前子樹先序序列起始指標
int *in, //當前子樹中序序列起始指標
int tLen) //當前子樹長度(節點個數)
{
/**
* 首先根據中序序列求出"左子樹的長度"和"右子樹的長度"
*
* Then:
* 左子樹"前序起始點" = 當前前序序列起始點 + 1;
* 左子樹"中序起始點" = 當前中序序列起始點;
*
* 右子樹"前序起始點" = 當前前序序列起始點 + 左子樹長度 + 1;
* 右子樹"中序起始點" = 當前中序起始點 + 左子樹長度 + 1;
*/
//求出根節點在中序序列中的索引(根據這個索引值求左右子樹長度)
int root_value = *pre;
int root_index = 0;
int *p = in;
for(int i=0;i<tLen;i++){
if(*p++ == root_value) break;
root_index++;
}
//求解左子樹和右子樹的長度
int lLen = root_index;
int rLen = tLen-root_index-1;
//遞迴左子樹
if(lLen != 0){
root->left = malloc_NODE(pre[1]);
rebuild_tree(root->left, pre+1, in, lLen);
}
else{
root->left = NULL;
}
//遞迴右子樹
if(rLen != 0){
root->right = malloc_NODE(pre[lLen+1]);
rebuild_tree(root->right, pre+lLen+1, in+lLen+1, rLen);
}else{
root->right = NULL;
}
}
//前序遍歷輸出
void printBST(NODE *node){
if(node != NULL){
cout<<node->value<<endl;
printBST(node->left);
printBST(node->right);
}
}
#define M 5
int main(){
int pre[M] = {1,2,4,5,3};
int in[M] = {4,2,5,1,3};
root = malloc_NODE(pre[0]);
//以root為根節點,按照pre和in兩個序列重構二叉樹
rebuild_tree(root, pre, in, M);
printBST(root);
return 0;
}