前面文章已讲到了二叉树的几种典型的遍历方式:
主要分为两大类
1. 深度优先(DFS):前序遍历,中序遍历,后序遍历
2. 宽度优先(BFS)
这几种遍历的具体实现前面的文章已经实现过了,这篇文章重点分析如何根据已有的前序遍历和中序遍历重建二叉树(或者给定中序遍历和后序遍历)
首先看一下三种遍历的差别:
简单来讲:
前序遍历顺序(中左右)
中序遍历(左中右)
后序遍历(左右中)
下面给出一个具体例子,看看三种遍历:
前序遍历
中序遍历
后序遍历
下面具体分析:
1.给定前序遍历和中序遍历重建二叉树(LeetCode105)
思路:
由上面的遍历过程不难发现,前序遍历的第一个元素必然是根节点。我们有了根节点根据中序遍历,就可以容易得到左子树和右子树的中序遍历(这两个子树任然是按中序遍历的顺序,这是我们接下来使用递归的原因),同时有了左子树和右子树节点数目,我们很容易根据前序遍历得到左右子树的前序遍历,
最后对左右子树使用两次递归。
具体代码如下
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& preorder, vector<int>& inorder) {
if(preorder.size()==0||inorder.size()==0)return 0;
auto root=new TreeNode(preorder[0]);
int index;
for(int i=0;i!=inorder.size();++i)
{
if(inorder[i]==root->val)
{
index=i;
}
}
vector<int>l_in(inorder.begin(),inorder.begin()+index);
vector<int>r_in(inorder.begin()+index+1,inorder.end());
vector<int>l_pr(preorder.begin()+1,preorder.begin()+1+l_in.size());
vector<int>r_pr(preorder.begin()+1+l_in.size(),preorder.end());
root->left=buildTree(l_pr,l_in);
root->right= buildTree(r_pr,r_in);
return root;
}
};
1.给定后序遍历和中序遍历重建二叉树(LeetCode106)
有了前面的根据前序遍历和中序遍历重建二叉树的分析,这里就相当简单了。
后序与前序最大的区别在于:前序遍历根节点在第一个元素,而后序遍历跟节点在最后一个元素。
这样讲上面的代码做一点小改动就可以完成这一题了。
代码实现:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* buildTree(vector<int>& inorder, vector<int>& postorder) {
if(postorder.size()==0||inorder.size()==0)return 0;
auto root=new TreeNode(postorder.back());
int index;
for(int i=0;i!=inorder.size();++i)
{
if(inorder[i]==root->val)
{
index=i;
}
}
vector<int>l_in(inorder.begin(),inorder.begin()+index);
vector<int>r_in(inorder.begin()+index+1,inorder.end());
vector<int>l_po(postorder.begin(),postorder.begin()+l_in.size());
vector<int>r_po(postorder.begin()+l_in.size(),postorder.end()-1);
root->left=buildTree(l_in,l_po);
root->right= buildTree(r_in,r_po);
return root;
}
};
二叉树的重建就分析完了,刚开始看也是一脸蒙蔽的,还是要多练习!!!