现在的位置: 首页 > 综合 > 正文

重构二叉树

2019年10月17日 ⁄ 综合 ⁄ 共 1394字 ⁄ 字号 评论关闭
/**
* 问题描述:
*	根据一颗二叉树的前序和中序遍历结果,重构这颗二叉树并输出后序遍历结果
*/
#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;
}

抱歉!评论已关闭.