剑指offer面试题6 前序遍历&中序遍历,后序遍历&中序遍历重构二叉树

重构二叉树目前主要是采取递归的方式

目前只能通过前序,中序 或者 后续,中序进行重构

前序和后序是不能够重构的,举个例子:

 前序: 1 2 4 7 3 5 6 8 

后续: 7 4 2 5 8 6 3 1 

是无法判断出7是节点4的左孩子还是右孩子的


首先讲解利用前序和中序进行重构

 前序: 1 2 4 7 3 5 6 8        中序:  4 7 2 1 5 3 8 6 

树结构是:

                                                               1

                                           2                                    3

                                   4                                     5                  6

                                        7                                               8

首先在前序中找到节点1表示为根节点,对应在中序中找到1, 1 左边的 472则是在左子树上,右边的是在又子树上,然后开始解左子树对应的节点

对应开始左节点2, 在中序中2 左边有4,7仍然是左节点,以此类推

对应的C++代码:

#include "static.h"
#include <iostream>
#include <stack>
using namespace std;
struct BinaryTreeNode
{
	int Value;
	BinaryTreeNode * pLeft;
	BinaryTreeNode * pRight;
	BinaryTreeNode()
	{
		Value = 0;
		pLeft = NULL;
		pRight = NULL;
	}
};

 BinaryTreeNode* ReconstructTree(int* startPreorder,int * endPreorder,int *startInorder,int * endInorder)
{
	BinaryTreeNode * root = new BinaryTreeNode;
	root->Value = startPreorder[0];
	if (startPreorder == endPreorder) //<满足条件返回对应的根节点的值
	{
		if (startInorder == endInorder && (*startInorder == *startPreorder))
		{
			return root;
		}
		else
		{
			throw std::exception("Invalid input");
		}
	}
	//<根据前向节点在中序遍历中找到对应的根节点
	int * rootInorder = startInorder;
	while ((root->Value != *rootInorder) && (rootInorder <= endInorder))
	{
		rootInorder++;
	}
	if (rootInorder > endInorder)
	{
		throw std::exception("Invalid input");//<在中序中找不到对应的根节点,抛出错误
	}
	int leftLength = rootInorder-startInorder;
	int * leftPreorderEnd = startPreorder+leftLength;  //<确定在前序遍历中对应左节点的末尾位置
	if (leftLength)
	{
		root->pLeft = <span style="color:#ff0000;">ReconstructTree(startPreorder+1,leftPreorderEnd,startInorder,rootInorder-1);</span>
	}
	if (leftLength < (endPreorder-startPreorder))
	{
		root->pRight = <span style="color:#ff0000;">ReconstructTree(leftPreorderEnd+1,endPreorder,rootInorder+1,endInorder);</span>
	}
	return root;
}
int main()
{  
	int FrontArry[8] = {1,2,4,7,3,5,6,8};
	int MiddleArry[8] = {4,7,2,1,5,3,8,6};
	if (FrontArry == NULL || MiddleArry == NULL)
	{
		return NULL;
	}
	BinaryTreeNode* Root = ReconstructTree(FrontArry,FrontArry+7,MiddleArry,MiddleArry+7);
	return 0;
}

后续: 7 4 2 5 8 6 3 1 

中序: 4 7 2 1 5 3 8 6 

#include <iostream>
#include <stack>
using namespace std;
struct BinaryTreeNode
{
	int Value;
	BinaryTreeNode * pLeft;
	BinaryTreeNode * pRight;
	BinaryTreeNode()
	{
		Value = 0;
		pLeft = NULL;
		pRight = NULL;
	}
};

 BinaryTreeNode* ReconstructTree(int* startBackorder,int * endBackorder,int *startInorder,int * endInorder)
{
	BinaryTreeNode * root = new BinaryTreeNode;
	root->Value = * endBackorder;
	if (startBackorder == endBackorder) //<满足条件返回对应的根节点的值
	{
		if (startInorder == endInorder && (*startInorder == *startBackorder))
		{
			return root;
		}
		else
		{
			throw std::exception("Invalid input");
		}
	}
	int * rootInoder = startInorder;
	while ((rootInoder <= endInorder) && (*rootInoder != root->Value))
	{
		rootInoder++;
	}
	if (rootInoder > endInorder)
	{
		throw std::exception("Invalid input");
	}
	int leftLength = rootInoder-startInorder;
	if (leftLength > 0)
	{
		root->pLeft = <span style="color:#ff0000;">ReconstructTree(startBackorder,startBackorder+leftLength-1,startInorder,rootInoder-1);</span>
	}
	if ((endBackorder-startBackorder) > leftLength)
	{
		root->pRight = <span style="color:#ff0000;">ReconstructTree(startBackorder+leftLength,endBackorder-1,rootInoder+1,endInorder);
</span>	}
	return root;
}
int main()
{  
	int BackArry[8] = {7,4,2,5,8,6,3,1};
	int MiddleArry[8] = {4,7,2,1,5,3,8,6};
	if (BackArry == NULL || MiddleArry == NULL)
	{
		return NULL;
	}
	BinaryTreeNode* Root = ReconstructTree(BackArry,BackArry+7,MiddleArry,MiddleArry+7);
	return 0;
}


两种遍历进行重构主要都是利用中序遍历中找到根节点之后,在根节点左边的是左节点数据,在右边的为右节点数据

然后 利用递归进行重构左孩子和右孩子

两者区别,前序遍历,根节点在最前面,后序遍历,根节点在最后面,所以两者在递归的过程中的传参数据有所不同。

后面将在这个例子上完成4中遍历对应的递归和非递归算法!

你可能感兴趣的:(数据结构,二叉树,遍历,二叉树重构)