转载注明出处:http://www.cnblogs.com/pk28/
补充树的3中遍历方式:
看下图:
先序遍历序列(4,1,3,2,6,5,7)
中序遍历序列(1,2,3,4,5,6,7)
后序遍历序列(2,3,1,5,7,6,4)
观察遍历的方式,我们可以知道,一棵树的先序遍历的第一个元素是树的根,后序遍历的最后一个元素是树的根。
如果给出一棵树的先序遍历或者后序遍历让你还原树,是不可能的。
一般的问题都是给出先序遍历和中序遍历让你还原树,或则给出后序遍历和中序遍历让你还原树。
那中序遍历能给出什么信息呢?单拿出中序遍历也是什么卵用没有,但是如果给出根的信息,我们就可以一点点知道树的结构。比如中序遍历(1,2,3,4,5,6,7),我们通过前序遍历知道树的总根是4,那么通过中序遍历我们就知道(1,2,3)是这棵树的左子树,(5,6,7)是这颗树的右子树。
以上是铺垫。
问题:
给出先序遍历和中序遍历创建二叉链表。
先序遍历(4,1,3,2,6,5,7)
中序遍历(1,2,3,4,5,6,7)
分析:
4是总根,带到中序遍历中(1,2,3)是左子树,(5,6,7)是右子树。
对于左子树(1,2,3)由于先序遍历先访问的1,那么1是树(1,2,3)的根,而1的左子树没有节点,右子树右2个节点(2,3)所以(2,3)成为根1的右子树。再看先序遍历,先访问的3多以3是子树(2,3)的根。所以1的右子树的根是3,那么到这,4的左子树的结构就得到了。
用同样的方式求右子树。因为先序遍历先访问的6,所以6是右子树(5,6,7)的根。而6的左子树有一个节点5,有边有一个节点7,所以知道6是根,就不用再往下找了。4的右子树结构就得到了。
代码实现:
#include <bits/stdc++.h>
using namespace std;
int zhong[7] = {1,2,3,4,5,6,7};
int qian[7] = {4,1,3,2,6,5,7};
struct TreeNode{
int val;
TreeNode* left;
TreeNode* right;
TreeNode(int x) : val(x), left(NULL), right(NULL) {}
};
TreeNode* build(int l1, int r1, int l2, int r2) { //l1 r1中序位置 l2 r2前序位置
//cout << "YES"<<endl;
if (l2 > r2) return NULL;
int val = qian[l2];
int p = l1;
while(zhong[p] != val) ++p;
int cnt = p - l1;//树大小
TreeNode* root = new TreeNode(val);
root->left = build(l1, p-1, l2+1, l2+cnt);
root->right = build(p+1, r1, l2+cnt+1, r2);
return root;
}
void dfs(TreeNode* root) { //先序遍历 检查一下
if (root == NULL) return ;
cout << root->val << endl;
dfs(root->left);
dfs(root->right);
}
int main() {
TreeNode*root = build(0, 6, 0, 6);
dfs(root);
return 0;
}