根据前序和中序序列重建二叉树 Construct Binary Tree from Preorder and Inorder Traversal

9oj编号1385。剑指6。Leetcode。

题目:根据二叉树的前序遍历序列和中序遍历序列,求得该二叉树的后序遍历序列。Given preorder and inorder traversal of a tree, construct the binary tree.

注意:有个前提,二叉树中的所有元素都不相同。

方法:

根据前序序列和中序序列重建二叉树原型,然后进行后序遍历。所以关键就在于重建二叉树。

使用递归的方法比较容易。如下图所示,对于二叉树的构建过程也是递归的。

根据前序和中序序列重建二叉树 Construct Binary Tree from Preorder and Inorder Traversal_第1张图片


首先把当前前序遍历序列的第一个元素作为root结点,并在在中序遍历中找到该root结点元素,那么root元素左边的若干个元素就是该root结点的左子树,root元素右边的若干个元素就是该root结点的右子树。然后递归地去构建各子树。

为了在递归时原地记录遍历序列,参数要记录前序遍历序列的开始指针和结束指针,中序遍历的开始指针和结束指针。


#include <iostream>
#include <cstdio>
using namespace std;

typedef struct BTreeNode{
	int value;
	BTreeNode *left;
	BTreeNode *right;
}Node,*BTree;


void pretraverse(BTree root)
{
	if(root != NULL)
	{
		printf("%d ", root->value);
		pretraverse(root->left);
		pretraverse(root->right);
	}
}

void intraverse(BTree root)
{
	if(root != NULL)
	{
		intraverse(root->left);
		printf("%d ", root->value);
		intraverse(root->right);
	}
}

void posttraverse(BTree root)
{
	if(root != NULL)
	{
		posttraverse(root->left);
		posttraverse(root->right);
		printf("%d ", root->value);
	}
}

BTree ConstructCore(int* startpreorder, int *endpreorder,
					int* startinorder, int* endinorder)
{
	int rootvalue = startpreorder[0];
	BTree root = new Node();
	root->value = rootvalue;
	root->left = root->right = NULL;

	if(startpreorder == endpreorder)
	{
		if(startinorder == endinorder && *startpreorder==*startinorder)
			return root;
		else
			throw "valid!";
	}

	//find root in inorder and conpute its location
	int *rootinorder = startinorder;
	while(rootinorder <= endinorder && *rootinorder != rootvalue)
		rootinorder++;
	if(rootinorder == endinorder && *rootinorder != rootvalue)
		throw "valid!";
	int leftlength = rootinorder - startinorder;
	int *leftpreorderend = startpreorder + leftlength;

	if(leftlength>0)
	{
		root->left = ConstructCore(startpreorder+1, leftpreorderend,
									startinorder, rootinorder-1);
	}
	if(leftlength < endpreorder - startpreorder)
	{
		root->right = ConstructCore(leftpreorderend+1, endpreorder,
									rootinorder+1, endinorder);
	}
	return root;
}

BTree Construct(int* preorder, int* inorder, int len)
{
	if(preorder == NULL || inorder == NULL || len < 0)
		return NULL;
	return ConstructCore(preorder, preorder+len-1, inorder, inorder+len-1);
}

int main()
{
	int n;
	int pre[1000], in[1000];
	while(scanf("%d",&n) != EOF)
	{
		for(int i=0;i<n;i++)
			scanf("%d", &pre[i]);
		for(int i=0;i<n;i++)
			scanf("%d", &in[i]);
		try
		{
			BTree tree = Construct(pre, in, n);
			//printf("PostOrder: ");
			posttraverse(tree);
			printf("\n");
		}
		catch(...)
		{
			printf("No\n");
		}
	}
	return 1;
}



LeeCode:

class Solution {
public:
    TreeNode *buildTree(vector<int> &preorder, vector<int> &inorder) {
        int n = preorder.size(); 
        if( n == 0)
            return NULL;
        return construct(preorder, inorder, 0, n-1, 0, n-1);
    }
    
    TreeNode *construct(vector<int> &preorder, vector<int> &inorder, int preleft, int preright, int inleft, int inright)
    {
        TreeNode *root = new TreeNode(preorder[preleft]);
        root->left = root->right = NULL;
        if(preleft == preright)
        {
            return root;
        }
        
        int i;
        for(i=inleft;i<=inright;i++)
        {
            if(inorder[i] == preorder[preleft])
                break;
        }
        if(i > inleft)
            root->left = construct(preorder, inorder, preleft+1, preleft+i-inleft, inleft, i-1);
        if(i < inright)
            root->right = construct(preorder, inorder, preleft+i-inleft+1, preright, i+1, inright);
        
        return root;
    }
};



编码心得:

1、二叉树遍历的时候在递归时别忘记判断递归结束条件,即指针为null。

2,C++的异常处理方法。g++和vs有一些不同。

一般的,可以在抛出异常时用 throw "出现异常";

捕捉异常用

try
{
捕捉异常
}
catch(...)
{
printf("说点什么\n");
}

当发现输入数据不符合逻辑且当时正处于递归深处时,返回语句不足以快速结束当前的处理过程,此时就可以借助异常处理来快速跳回最外层。



变种题目:

1、根据后序遍历序列和中序遍历序列,求得前序遍历序列。其思想和本题目一致。

2、根据前序遍历序列和后续遍历序列,求得所有可能的中序遍历序列。

你可能感兴趣的:(根据前序和中序序列重建二叉树 Construct Binary Tree from Preorder and Inorder Traversal)