二叉树的递归遍历

首先,二叉树递归遍历分为先序遍历、中序遍历和后序遍历。

先序遍历为:根节点+左子树+右子树

中序遍历为:左子树+根节点+右子树

后序遍历为:左子树+右子树+根节点

(只要记住根节点在哪里就是什么遍历,且都是先左再右)

举个例子,如二叉树:

这棵树的先序遍历为:1 2 3 4 5

中序遍历为:2 1 4 3 5

后序遍历为:2 4 5 4 1

以上类容比较好理解,然后就是干活算法了

问,得知其中两个遍历,是否能构造出二叉树以求出第三个遍历?

是可以的。

首先我要说明我喜欢用的二叉树储存方式:两个数组:lefttree[]、righttree[];

其中lefttree[i]、righttree[i]代表的是根节点i的左子树和右子树(0表示没有)

例如上图为

lefttree:2 0 4 0 0

righttree:3 0 5 0 0

现在问题来了:

一、得知先序遍历和中序遍历,怎么得到二叉树?

先上数据:

5 //二叉树节点个数

1 2 3 4 5 //先序遍历

2 1 4 3 5 //中序遍历

我们知道,先序遍历的第一个永远是根节点,因此我们确切得得出1是根节点

接着,我们在中序遍历终找到2,显然得出2的左边是左子树,右边是右子树。

我们递归搜索左子树,此时2为根节点,发现2的左右在中序遍历中没有数了,于是返回2到lefttree[1]里面

然后看先序遍历,遇到3,将3为根节点,发现在中序遍历中3的左边有4,于是递归左子树到4。

到4以后发现在中序遍历4的左右没有数了,返回lefttree[3]=4

返回到3以后,发现3在中序遍历的右边有一个5,说明5是3的右子树,递归到5

发现5左右没有了,返回righttree[3]=5

3的搞完了继续返回,righttree[2]=3

然后完事大吉,看代码

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int n;
int pre_order[100010];//先序遍历
int in_order[100010];//中序遍历
int lefttree[100010];//左子树
int righttree[100010];//右子树
int build(int in_left,int in_right,int pre_left,int pre_right)//主要函数,前两个参数是中序遍历从几到几的递归区间,后两个是先序遍历的。
{
    if(in_right < in_left)//此节点不存在,直接返回0
        return 0;
    int root=pre_order[pre_left];//先序遍历的第一个为根节点
    int k=in_left;
    while(in_order[k]!=root)//看当前的跟在中序遍历中的下标是多少
        k++;
    int cnt=k-in_left;//当先根的左子树节点个数
    lefttree[root]=build(in_left,k-1,pre_left+1,pre_left+cnt);//递归左子树,注意每个参数都很重要    
    righttree[root]=build(k+1,in_right,pre_left+cnt+1,pre_right);//递归右子树,参数同样重要
    return root;//返回根节点到上一个根节点的子树数组。
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)//读入
        cin>>pre_order[i];
    for(int i=1;i<=n;i++)
        cin>>in_order[i];
        build(1,n,1,n);//调用
}

以上是先中遍历构造

二、知道中序遍历后序遍历,构造二叉树

其实,这么说,这个和前面的那个很像

只不过是把先序遍历倒过来成了后序遍历

代码如下:

 

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
int n;
int in_order[100010];
int post_order[100010];
int lefttree[100010];
int righttree[100010]; 
int build(int in_left,int in_right,int post_left,int post_right)
{
    if(in_right < in_left)
        return 0;
    int root=post_order[post_right];//这里不同了
    int k=in_left;
    while(in_order[k]!=root)
        k++;
    int cnt=k-in_left;
    lefttree[root]=build(in_left,k-1,post_left,post_left+cnt-1);//这里不同了
    righttree[root]=build(k+1,in_right,post_left+cnt,post_right-1);
    return root;
}
int main()
{
    cin>>n;
    for(int i=1;i<=n;i++)
        cin>>in_order[i];
    for(int i=1;i<=n;i++)
        cin>>post_order[i];
    build(1,n,1,n);
}

谢谢大家,关于二叉树遍历的讲解就结束了,求关注!!!

 

posted @ 2017-09-21 22:22  Dijkstra·Liu  阅读(2542)  评论(0编辑  收藏  举报