重构二叉树目前主要是采取递归的方式
目前只能通过前序,中序 或者 后续,中序进行重构
前序和后序是不能够重构的,举个例子:
前序: 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中遍历对应的递归和非递归算法!