zoukankan      html  css  js  c++  java
  • 二叉树的递归遍历

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

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

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

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

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

    举个例子,如二叉树:

    这棵树的先序遍历为: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);
    }

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

  • 相关阅读:
    《Redis 设计与实现》读书笔记(四)
    《Redis 设计与实现》读书笔记(三)
    《Redis 设计与实现》读书笔记(二)
    《Redis 设计与实现》读书笔记(一)
    《Mysql技术内幕-InnoDB存储引擎》读书笔记 (一)
    Python调试工具
    记一次偶发的bug排查——redis-py-cluster库的bug
    苹果支付的这些漏洞,你都堵上了吗?
    微软消息队列-MicroSoft Message Queue(MSMQ)队列的C#使用
    Quartz.net设置任务中同时最多运行一个实例 [DisallowConcurrentExecution]
  • 原文地址:https://www.cnblogs.com/jason2003/p/7571651.html
Copyright © 2011-2022 走看看