二叉树的遍历有三种:
1.前序遍历:遍历顺序是:先访问根节点,再遍历左子树,最后遍历右子树;
2.中序遍历:遍历顺序是:先遍历左子树,再访问根节点,最后遍历右子树;
3.后序遍历:遍历顺序是:先遍历左子树,再遍历右子树,最后访问根节点;
4.层序遍历:遍历顺序是:一层一层的遍历。
可以知道的是,无论我们使用哪种遍历方式,其实质都是dfs(深度优先搜索), 除了层序遍历有点不一样。
代码实现:(假设已经给出树的序列)
1.前序遍历:
#include<iostream>
using namespace std;
void pre(int a)
{
cout << a;//先输出根节点
if(tree[x].left)pre(tree[x].left);//搜素左子树
if(tree[x].right)pre(tree[x].right);//搜索右子树
}
2.中序遍历:
#include<iostream>
using namespace std;
void in(int a)
{
if(tree[x].left)pre(tree[x].left);//先搜素左子树
cout << a;//再输出根节点
if(tree[x].right)pre(tree[x].right);//最后搜索右子树
}
3.后序遍历:
#include<iostream>
using namespace std;
void post(int a)
{
if(tree[x].left)pre(tree[x].left);//先搜素左子树
if(tree[x].right)pre(tree[x].right);//再搜索右子树
cout << a;//最后输出根节点
}
4.层序遍历:
#include<iostream>
using namespace std;
const int N = 100010;//最坏情况是可能会很大
int tree[N], maxn;
void layer(int a, int idx)
{
tree[idx] = a;//直接重建树
maxn = max(maxn, idx);//记录最后的点
if(tree[x].left)pre(tree[x].left, idx * 2);//先搜素左子树
if(tree[x].right)pre(tree[x].right, idx * 2 + 1);//最后搜索右子树
}
void puts_ceng()
{
for(int i = 1; i <= maxn; i ++)
if(tree[i])
cout << tree[i] << (i != maxn ? " " : "\n");
}
以上就是四种遍历的实现,但是我们通常遇不到这么简单的遍历问题,通常都是给出两种遍历,让你以此建树,顺便输出第三种遍历;
A.给出前序遍历和中序遍历,求其后序遍历:
例:
前序:1 3 4 7 2;
中序:4 3 7 1 2;
解决方案:
1.首先我们可以知道,前序遍历是先输出根节点再输出左子树,而中序遍历是先输出完左子树才会输出根节点,依次我们根据前序遍历的 1 来操作中序遍历划分整个树分别获取各个树的大小;
左子树:4 3 7
右子树:2
再根据前序遍历的 3 来继续划分左子树
左子树:4
右子树:7
......
由上述操作我们不难看出,根据遍历的性质,我们可以递归的建树,每次都找到前序遍历的根节点,根据根节点划分中序遍历为左子树和右子树。
代码实现:
#include<iostream>
using namespace std;
const int N = 100;
int a[N], b[N];
void built_tree(int l1, int r1, int l2, int r2)
{
for(int i = l2; i <= r2; i ++)//遍历中序找到根
{
if(a[l1] == b[i])
{
// i - l2 是左树的长度
// l1 + i - l2 == 下次递归前序遍历的长度
built_tree(l1 + 1, l1 + i - l2, l2, i - 1);//左子树的搜素
built_tree(l1 + i - l2 + 1, r1, i + 1, r2);//右子树的搜索
cout << a[l1] << " ";//最后输出根节点
return;
}
}
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];//前序
for(int i = 1; i <= n; i ++) cin >> b[i];//中序
built_tree(1, n, 1, n);
return 0;
}
B.给出中序遍历和后序遍历,求前序遍历
例:
中序:4 3 7 1 2
后序:4 7 3 2 1
解决方案:
依旧是根据遍历性质,中序:左,根,右;后序遍历是先左子树后右子树,最后根子树;依此性质,我们可知后序遍历的最后一个点是根节点,再原理同上建树。
代码实现:
#include<iostream>
using namespace std;
const int N = 100;
int a[N], b[N];
void built_tree(int l1, int r1, int l2, int r2)
{
for(int i = l2; i <= r2; i ++)//遍历中序找到根
{
if(a[r1] == b[i])
{
// r2 - i 是右树的长度
cout << a[r1] << " ";//先输出根节点
built_tree(l1, r1 - (r2 - i) - 1, l2, i - 1);//左子树的搜素
built_tree(l1 + (r2 - i), r1 - 1, i + 1, r2);//右子树的搜索
return;
}
}
}
int main()
{
int n;
cin >> n;
for(int i = 1; i <= n; i ++) cin >> a[i];
for(int i = 1; i <= n; i ++) cin >> b[i];
built_tree(1, n, 1, n);
return 0;
}
C.给出前序遍历和后序遍历...能求中序遍历吗?
求不出具体的中序遍历,只能求可能的中序遍历,根据前,后序遍历的性质
前:根——左——右
后:左——右——根
我们不能确定具体的子树大小,只能猜测,所以这个问题个人不做深究......
结束...................