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