重構二叉樹

小弟季義欽發表於2012-11-12
/**
* 問題描述:
*	根據一顆二叉樹的前序和中序遍歷結果,重構這顆二叉樹並輸出後序遍歷結果
*/
#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;
}

相關文章