二叉树的遍历有三种,分别是前序遍历、中序遍历和后序遍历,我们来看看这三种遍历的特性:
前序遍历(根-->左-->右)
1.访问根节点
2.前序遍历左子树
3.前序遍历右子树
中序遍历(左-->根-->右)
1.中序遍历左子树
2.访问根节点
3.中序遍历右子树
后序遍历(左-->右-->根)
1.后序遍历左子树
2.后序遍历右子树
3.访问根节点
一、已知前序、中序遍历,求后序遍历
已知
前序遍历: ABGDECFH
中序遍历: GBEDAFCH
构建二叉树步骤:
根据前序遍历的特点,我们知道根结点root为A;
观察中序遍历GBEDAFCH。其中root节点A的左侧GBED必然是root的左子树,右侧FCH必然是root的右子树。同时,这个也分别是左子树和右子树的中序遍历的序列;
在前序遍历遍历完根节点后,接着执行前序遍历左子树,注意,是前序遍历,什么意思?就是把左子树当成一棵独立的树,执行前序遍历,同样先访问左子树的根,第2步我们已经知道左子树是BGDE(前序遍历序列)了,由此可以得到,左子树的根是B,那么在这一步得到左子树的根是B;
从第2步得到的中序遍历的节点序列中,找到B,发现B左边只有一个G,说明B的左子树只有一个叶子节点,B的右边呢?我们可以得到B的右子树有ED,再看前序遍历的序列,发现D在前,也就是说,D是先前序遍历访问的,则得到E是D的左子树,只有一个叶子节点。到这里,我们可以得到这棵树的根结点和左子树的结构了,如下图:
5. 接着看右子树,在第2步的时候已经知道右子树是FCH这三个节点,那么先看前序遍历的序列,先出现的是C,那么C就是右子树的根结点,看右子树的中序遍历为FCH,所以F和H就分别是它的左子树和右子树,因此,右子树的结构就出来了,如下图:
6. 把左子树和右子树连接起来,可以得到整棵树的结构:
7. 最后由二叉树的结构可以得到后序遍历序列为:GEDBFHCA
二、已知中序、后序遍历,求前序遍历
已知
中序遍历: GBEDAFCH
后序遍历:GEDBFHCA
步骤和上面的类似,还是得先找出根结点,由后序遍历的特点,根结点root在最后,所以根结点为A,再由中序遍历可以知道左子树和右子树分别为GBED、FCH;再按照上面的步骤递归分别求出左右子树即可得解。
三、已知前序、后序遍历,求中序遍历
已知前序、中序或者中序、后序都可以唯一确定一棵二叉树,但是已知前序、后序是无法唯一确定一棵二叉树的,解不唯一。
四、题目描述
输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含重复的数字。例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7,2,1,5,3,8,6},则重建二叉树并返回。
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int s = pre.size();
if (s == 0)
return NULL;
vector<int> pre_left, pre_right, vin_left, vin_right;
TreeNode* node = new TreeNode(pre[0]);
int i = 0;
for (;i < pre.size();i++)
{
if (pre[0] == vin[i])
break;
}
for (int j = 1; j < pre.size(); j++)
{
if (j <= i)
pre_left.push_back(pre[j]);
else
pre_right.push_back(pre[j]);
}
for (int j = 0;j < vin.size();j++)
{
if (j < i)
vin_left.push_back(vin[j]);
else if (j>i)
vin_right.push_back(vin[j]);
}
node->left = reConstructBinaryTree(pre_left, vin_left);
node->right = reConstructBinaryTree(pre_right, vin_right);
return node;
}
};