二叉树有三种基本的遍历方式:前序遍历(根节点-左节点-右节点)、中序遍历(左节点-根节点-右节点)和后续遍历(左节点-右节点-根节点)。每一种遍历方式得到的序列并不能唯一的确定一棵二叉树,需要结合,比如中序遍历和前序遍历、中序遍历和后序遍历都能够唯一地确定一棵二叉树,但是前序遍历和后序遍历却唯一地确定二叉树(我理解为前序遍历和后序遍历左右节点的相对位置是一样的,所以没有办法唯一的确定左右节点的位置)。
示例
根据前序遍历和中序遍历确定二叉树:
前序遍历结果:{1,2,4,7,3,5,6,8},
中序遍历结果:{4,7,2,1,5,3,8,6}
然后递归的建立左右子树即可,代码如下:
/**
* Definition for binary tree
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode(int x) : val(x), left(NULL), right(NULL) {}
* };
*/
class Solution {
public:
TreeNode* reConstructBinaryTree(vector<int> pre,vector<int> vin) {
int index=0;
int len=vin.size();
if(len<1) return NULL;
int i;
for(i=0;i<len;i++)
if(vin[i] == pre[0])
{
index=i;
break;
}
vector<int> left_pre,right_pre;
vector<int> left_vin,right_vin;
for(i=0;i<index;i++){
left_vin.push_back(vin[i]);
left_pre.push_back(pre[i+1]);
}
for(i=index+1;i<len;i++){
right_vin.push_back(vin[i]);
right_pre.push_back(pre[i]);
}
TreeNode* root=new TreeNode(pre[0]);
root->left=reConstructBinaryTree(left_pre,left_vin);
root->right=reConstructBinaryTree(right_pre,right_vin);
left_vin.clear();
right_vin.clear();
left_pre.clear();
right_pre.clear();
return root;
}
};
二叉树还有一种基本遍历方式,即层序遍历,由于遍历过程中,左右子树相对位置同前序和后序遍历,因此将其和中序遍历结果结合使用,仍然可以唯一地确定一棵二叉树。
比如层序遍历结果:{3,5,4,2,6,7,1}
中序遍历结果:{2,5,3,6,4,7,1}
使用层序遍历和中序遍历结果去确定一棵二叉树的方法和使用前序中序遍历结果不同,当确定了左右子树的元素之后,在层序遍历结果中出现最早的就是左右子树的根节点,所以每一次对左右子树进行递归的时候,都需要遍历层序遍历的结果,找到当前还没有被访问到的最前面的节点元素。代码如下:
#include <iostream>
#include <string>
#include <vector>
#include <sstream>
using namespace std;
struct TreeNode{
int val;
TreeNode *left,*right;
TreeNode(int x):val(x),left(NULL),right(NULL){}
};
class Solution{
private:
TreeNode* root;
vector<int> leaf;
vector<int> lev;
vector<int> vin;
vector<int> visit;
public:
void construct(vector<int> lev_tree,vector<int> vin_tree){
lev=lev_tree;
vin=vin_tree;
lev_tree.clear();
vin_tree.clear();
int len=vin.size();
visit.resize(len,0);
root=construct_Tree(0,len-1);
}
TreeNode* construct_Tree(int left,int right){
if(left>right)return NULL;
TreeNode* root=NULL;
int i,index,j;
int flag=0;
for(i=0;i<lev.size();i++){
if(visit[i]==0)
for(j=left;j<=right;j++)
if(vin[j]==lev[i]){
index=j;
flag=1;
break;
}
if(flag)
break;
}
if(flag){
visit[i]==1;
if((index==left) && (right==index))
leaf.push_back(vin[left]);
root=new TreeNode(vin[index]);
root->left=construct_Tree(left,index-1);
root->right=construct_Tree(index+1,right);
}
return root;
}
};