重建二叉树
2017-12-06 13:35
232 查看
问题描述:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
函数接口: TreeNode* reConstructBinaryTree(vector pre,vector vin)
注意:不一定非要根据接口去写,自己能实现算法就可以了
解题方法
1.因为前序遍历的顺序就是按照根左右来创建的,所以参考前序遍历的顺序可以按照顺序来创建根结点,因为中序遍历的顺序是左根右,所以参考中序遍历的方法可以确定根节点的左子树和右子数,然后递归先创建左子树,然后创建右子树。
举个例子:
比如题中给出的数据
前序:1 2 4 7 3 5 6 8
中序:4 7 2 1 5 3 8 6
1.根据前序顺序首先根节点为1,所以在中序中找到1结点所在的位置,这个时候1结点左边的4 7 2 为根节点的左子树,右边的5 3 8 6为跟结点的右子数
2.根据前序根节点为2.找到中序中的2的位置,现在2的左边的4 7为2的左子树,因为1为根节点所以2没有右子数,
3.根据前序根节点为4,找到中序中4的位置。因为4的左边没有元素,所以4没有左子树,4的右边为7.所以4的右子数为7,这个时候整个树的左子树就出来了,如下图
下面开始创建根节点1的右子数
5.前序三为根节点,在中序中找到3的位置,所以5是3的左子树,8 6 是三的右子树
6.创建根节点5,5没有左右子树
7.创建根节点 6,在中序中找到6的位置,所以8是6的左子树,至此整个树就创建完成了。如下图
下面给出算法代码1:
算法代码2:
下面给出完整代码和测试结果:
结果如下:
这里只给出了s1的结果指向图,能做到这个题的应该懂这个图,这里就不多说了(直接去监视里面看就可以了,不懂的自己摸索),s2的自己去看看吧,两个结果是一样的,完整的创建了整个二叉树!
函数接口: TreeNode* reConstructBinaryTree(vector pre,vector vin)
注意:不一定非要根据接口去写,自己能实现算法就可以了
解题方法
1.因为前序遍历的顺序就是按照根左右来创建的,所以参考前序遍历的顺序可以按照顺序来创建根结点,因为中序遍历的顺序是左根右,所以参考中序遍历的方法可以确定根节点的左子树和右子数,然后递归先创建左子树,然后创建右子树。
举个例子:
比如题中给出的数据
前序:1 2 4 7 3 5 6 8
中序:4 7 2 1 5 3 8 6
1.根据前序顺序首先根节点为1,所以在中序中找到1结点所在的位置,这个时候1结点左边的4 7 2 为根节点的左子树,右边的5 3 8 6为跟结点的右子数
2.根据前序根节点为2.找到中序中的2的位置,现在2的左边的4 7为2的左子树,因为1为根节点所以2没有右子数,
3.根据前序根节点为4,找到中序中4的位置。因为4的左边没有元素,所以4没有左子树,4的右边为7.所以4的右子数为7,这个时候整个树的左子树就出来了,如下图
下面开始创建根节点1的右子数
5.前序三为根节点,在中序中找到3的位置,所以5是3的左子树,8 6 是三的右子树
6.创建根节点5,5没有左右子树
7.创建根节点 6,在中序中找到6的位置,所以8是6的左子树,至此整个树就创建完成了。如下图
下面给出算法代码1:
PNode _reConstructBinaryTree(vector<int> pre, vector<int> vin)//重建二叉树的接口 { if (pre.empty()||vin.empty()) return NULL; int data = pre.front(); int n = vin.size(); int lenth = 0; int index = 0; PNode cur = new Node(data);//创建根节点 //下面开始在中序遍历中找根结点的左子树和右子数 for (int i = 0; i < n; i++) { if (vin[i] == data) { index = i;//找到右子树中对应的位置 lenth = n - i - 1;//记录中序遍历右子树的起点位置 break; } } vector<int> preleft(pre.begin() + 1, pre.begin() + index+1);//记录左子树的前序遍历的顺序 vector<int> vinleft(vin.begin(), vin.begin() + index);//记录左子树中序遍历的顺序 vector<int> preright(pre.begin() +index+1, pre.begin()+lenth+index+1);//记录右子数的前序遍历顺序 vector<int> vinright(vin.begin() +index+1, vin.begin() + lenth+index+1);//记录右子树的中序遍历顺序 cur->Lchild = _reConstructBinaryTree(preleft, vinleft); cur->Rchild = _reConstructBinaryTree(preright, vinright); return cur; }
算法代码2:
PNode _ConstructBinTree(int *preOrder, int *inOrder, int length)//重建二叉树 { if (NULL == preOrder || NULL == inOrder || length <= 0) return NULL; int data = preOrder[0]; PNode cur = new Node(data); int index = 0; int lenth = 0; for (int i = 0; i < length; i++)//根据中序找到根节点的左右子树 { if (data == inOrder[i]) { index = i;//根节点在中序中的位置 lenth = length - i -1; break; } } int *preleft = preOrder + 1;//记录左子树前序 int *inleft = inOrder;//记录左子树中序 int *preright = preOrder + index + 1;//记录右子树前序 int *inright = inOrder + index + 1;//记录右字树中序 cur->Lchild = _ConstructBinTree(preleft, inleft, index);//创建左子树 cur->Rchild = _ConstructBinTree(preright, inright, lenth);//创建右子数 return cur; }
下面给出完整代码和测试结果:
#include<iostream>
#include<vector>
using namespace std;
template<class T>
struct BinTreeNode//二叉树的结点
{
T _data;
BinTreeNode<T> *Lchild;
BinTreeNode<T> *Rchild;
BinTreeNode(T& data)
:_data(data)
, Lchild(NULL)
, Rchild(NULL){}
};
template<class T>
class TreeNode
{
typedef BinTreeNode<T> *PNode;
typedef BinTreeNode<T> Node;
public:
PNode head;
TreeNode()
:head(NULL)
{}
void reConstructBinaryTree(vector<int> pre, vector<int> vin)//调用重建二叉树的函数
{
head = _reConstructBinaryTree(pre, vin);
}
void ConstructBinTree(int *preOrder, int *inOrder, int length)
{
head = _ConstructBinTree(preOrder, inOrder, length);
}
private:
PNode _reConstructBinaryTree(vector<int> pre, vector<int> vin)//重建二叉树的接口
{
if (pre.empty()||vin.empty())
return NULL;
int data = pre.front();
int n = vin.size();
int lenth = 0;
int index = 0;
PNode cur = new Node(data);//创建根节点
//下面开始在中序遍历中找根结点的左子树和右子数
for (int i = 0; i < n; i++)
{
if (vin[i] == data)
{
index = i;//找到右子树中对应的位置
lenth = n - i - 1;//记录中序遍历右子树的起点位置
break;
}
}
vector<int> preleft(pre.begin() + 1, pre.begin() + index+1);//记录左子树的前序遍历的顺序
vector<int> vinleft(vin.begin(), vin.begin() + index);//记录左子树中序遍历的顺序
vector<int> preright(pre.begin() +index+1, pre.begin()+lenth+index+1);//记录右子数的前序遍历顺序
vector<int> vinright(vin.begin() +index+1, vin.begin() + lenth+index+1);//记录右子树的中序遍历顺序
cur->Lchild = _reConstructBinaryTree(preleft, vinleft);
cur->Rchild = _reConstructBinaryTree(preright, vinright);
return cur;
}
PNode _ConstructBinTree(int *preOrder, int *inOrder, int length)//重建二叉树 { if (NULL == preOrder || NULL == inOrder || length <= 0) return NULL; int data = preOrder[0]; PNode cur = new Node(data); int index = 0; int lenth = 0; for (int i = 0; i < length; i++)//根据中序找到根节点的左右子树 { if (data == inOrder[i]) { index = i;//根节点在中序中的位置 lenth = length - i -1; break; } } int *preleft = preOrder + 1;//记录左子树前序 int *inleft = inOrder;//记录左子树中序 int *preright = preOrder + index + 1;//记录右子树前序 int *inright = inOrder + index + 1;//记录右字树中序 cur->Lchild = _ConstructBinTree(preleft, inleft, index);//创建左子树 cur->Rchild = _ConstructBinTree(preright, inright, lenth);//创建右子数 return cur; }
};
int main()
{
vector<int> pre = { 1, 2, 4, 7, 3, 5, 6, 8 };
vector<int> vin = { 4, 7, 2, 1, 5, 3, 8, 6 };
TreeNode<int> s1;
TreeNode<int> s2;
int pree[] = { 1, 2, 4, 7, 3, 5, 6, 8 };
int vinn[] = { 4, 7, 2, 1, 5, 3, 8, 6 };
s1.reConstructBinaryTree(pre, vin);
s2.ConstructBinTree(pree, vinn, 8);
system("pause");
return 0;
}
结果如下:
这里只给出了s1的结果指向图,能做到这个题的应该懂这个图,这里就不多说了(直接去监视里面看就可以了,不懂的自己摸索),s2的自己去看看吧,两个结果是一样的,完整的创建了整个二叉树!
相关文章推荐
- POJ 2255Tree Recovery 二叉树重建(根据前序遍历和中序遍历写出后序遍历)
- 习题6-3 二叉树重建(Tree Recovery, ULM 1997, UVa 536)
- 由前序和中序数组重建二叉树
- 编程之美读书笔记_3.9_重建二叉树
- 根据先序遍历数列和中序遍历数列重建二叉树
- 重建二叉树
- 重建二叉树 的 非递归算法(已知前序和中序)输出 层续和后续
- 《剑指offer》刷题笔记(树):重建二叉树
- 二叉树重建
- 重建二叉树(Java)
- hihoCoder - 1049 - 后序遍历 (二叉树的重建!!)
- 根据前序遍历和中序遍历重建二叉树的Java实现
- 根据中序遍历和后序遍历重建二叉树
- 剑指offer--重建二叉树
- 依据前序和中序列 重建二叉树
- UVa 11234 Expressions (二叉树重建&由叶往根的层次遍历)
- 重建二叉树
- 重建二叉树
- [剑指offer]算法4 重建二叉树
- 二叉树(14)----由前序遍历和中序遍历重建二叉树,递归方式