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

    已知前序和中序,求后序遍历

    假设前序遍历为 adbgcefh, 中序遍历为 dgbaechf 
    前序遍历是先访问根节点,然后再访问子树的,而中序遍历则先访问左子树再访问根节点 
    那么把前序的 a 取出来,然后查找 a 在中序遍历中的位置就得到 dgb a echf 
    那么我们就知道 dgb 是左子树 echf 是右子树,因为数量要吻合 
    所以前序中相应的 dbg 是左子树 cefh 是右子树 ;

    下图为求出的二叉树的图形:

    已知后序和中序,求前序遍历

    后序遍历为 gbdehfca,中序遍历为 dgbaechf 
    后序遍历中的最后一个元素是根节点,a,然后查找中序中a的位置 
    把中序遍历分成 dgb a echf,而因为节点个数要对应 
    后序遍历分为 gbd ehfc a,gbd为左子树,ehfc为右子树,这样又可以递归计算了
    最后形成的二叉树如下图片所示:

    这种题一般有二种形式,共同点是都已知中序序列。如果没有中序序列,是无法唯一确定一棵树的,证明略。

    一、已知二叉树的前序序列和中序序列,求解树。

    1、确定树的根节点。树根是当前树中所有元素在前序遍历中最先出现的元素。

    2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。

    3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。

    二、已知二叉树的后序序列和中序序列,求解树。

    1、确定树的根。树根是当前树中所有元素在后序遍历中最后出现的元素。

    2、求解树的子树。找出根节点在中序遍历中的位置,根左边的所有元素就是左子树,根右边的所有元素就是右子树。若根节点左边或右边为空,则该方向子树为空;若根节点左边和右边都为空,则根节点已经为叶子节点。

    3、递归求解树。将左子树和右子树分别看成一棵二叉树,重复1、2、3步,直到所有的节点完成定位。

    举例说明:根据已知求解二叉树

    中序序列 HLDBEKAFCG
    后序序列 LHDKEBFGCA

    1、在后序序列LHDKEBFGCA中最后出现的元素为A,HLDBEK|A|FCG
    2、在后序序列LHDKEB中最后出现的元素为B,HLD|B|EK|A|FCG
    3、在后序序列LHD中最后出现的元素为D,HL|D|B|EK|A|FCG
    4、在后序序列LH中最后出现的元素为H,H|L|D|B|EK|A|FCG
    5、在后序序列KE中最后出现的元素为E,H|L|D|B|E|K|A|FCG

    5、在后序序列FGC中最后出现的元素为C,H|L|D|B|E|K|A|F|C|G
    6、所有元素都已经定位,二叉树求解完成。

                     A
                  /     
                 B       C
                /      /  
               D  E     F   G
              /    
             H      K                    
                                       
               L                     
    代码如下:
    Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->  1 /*
        功能: 1.利用树的前序和中序序列创建树
              2.利用树的后序和中序序列创建树
    */
    #include <iostream>
    #include <cstring>
    using namespace std;
    
    char pre[50] = "ABDHLEKCFG";        //前序序列
    char mid[50] = "HLDBEKAFCG";        //中序序列
    char post[50] = "LHDKEBFGCA";        //后序序列
    
    typedef struct _Node
    {
        char v;
        struct _Node *left;
        struct _Node *right;
    }Node, *PNode;
    
    void PostTravelTree(PNode pn);        //树的后序递归遍历
    void PreTravelTree(PNode pn);        //树的前序递归遍历
    void PreMidCreateTree(PNode &pn, int i, int j, int len);        //利用前序中序序列创建树
    void PostMidCreateTree(PNode &pn, int i, int j, int len);        //利用后序中序序列创建树
    int Position(char c);                //确定c在中序序列mid中的下标,假设树的各个节点的值各不相同
    
    
    int main() 
    { 
        PNode root1 = NULL, root2= NULL;
    
        PreMidCreateTree(root1, 0, 0, strlen(mid));
        PostTravelTree(root1); cout<<endl;    
        PostMidCreateTree(root2, strlen(post)-1, 0, strlen(mid));
        PreTravelTree(root2); cout<<endl;    
    
        return 0;
    }
    
    
    int Position(char c)
    {
        return strchr(mid,c)-mid;
    }
    
    
    /*  利用前序中序序列创建树,参考了http://hi.baidu.com/sulipol/blog/item/f01a20011dcce31a738b6524.html
     *的实现,代码十分简洁,竟然只有短短的"令人发指"的8行,递归实在太彪悍了!!!!!!!!!!!!!!!!!!!!!
     *        i: 子树的前序序列字符串的首字符在pre[]中的下标
     *        j: 子树的中序序列字符串的首字符在mid[]中的下标
     *      len: 子树的字符串序列的长度
     */
    void PreMidCreateTree(PNode &pn, int i, int j, int len)
    {
        if(len <= 0)
            return;
        
        pn = new Node;
        pn->v = pre[i];
        int m = Position(pre[i]);
        PreMidCreateTree(pn->left, i+1, j, m-j);            //m-j为左子树字符串长度
        PreMidCreateTree(pn->right, i+(m-j)+1, m+1, len-1-(m-j));    //len-1-(m-j)为右子树字符串长度
    }
    
    
    /*  利用后序中序序列创建树
     *        i: 子树的后序序列字符串的尾字符在post[]中的下标
     *        j: 子树的中序序列字符串的首字符在mid[]中的下标
     *      len: 子树的字符串序列的长度
     */
    void PostMidCreateTree(PNode &pn, int i, int j, int len)
    {
        if(len <= 0)
            return;
    
        pn = new Node;
        pn->v = post[i];
        int m = Position(post[i]);
        PostMidCreateTree(pn->left, i-1-(len-1-(m-j)), j, m-j);//注意参数:m-j左子树的长度,len-1-(m-j)右子树的长度
        PostMidCreateTree(pn->right, i-1, m+1, len-1-(m-j));
    }
    
    
    void PostTravelTree(PNode pn)        //后序递归遍历
    {
        if(pn)
        {
            PostTravelTree(pn->left);    
            PostTravelTree(pn->right);
            cout<<pn->v<<" ";
        }
    }
    
    
    void PreTravelTree(PNode pn)        //前序递归遍历
    {
        if(pn)
        {
            cout<<pn->v<<" ";
            PreTravelTree(pn->left);    
            PreTravelTree(pn->right);
        }
    }
  • 相关阅读:
    虚拟设备 ide1:0 将开始断开
    虚拟机集群启动 某一台启动失败
    jeesite1,工具类,文件介绍
    line-clamp
    js中同名的函数的调用情况
    获取子页面iframe的点击事件及iframe跨域的交互
    Docker环境搭建入门
    软件工程课后作业:论我对百度搜索的看法
    第二阶段第十天12.10
    软件工程:用户场景描述
  • 原文地址:https://www.cnblogs.com/zjfjava/p/6035596.html
Copyright © 2011-2022 走看看