精华内容
下载资源
问答
  • 中序遍历

    2019-11-01 13:58:50
    一、中序遍历   先遍历左子树,然后访问根节点,然后遍历右子树。 二、训练 1、二叉树的中序遍历   通常来说,对于二叉搜索树,我们可以通过中序遍历得到一个递增的有序序列。 ...

    一、中序遍历

      先遍历左子树,然后访问根节点,然后遍历右子树。

    二、训练

    1、二叉树的中序遍历

      通常来说,对于二叉搜索树,我们可以通过中序遍历得到一个递增的有序序列。
    2、两数之和-双指针

    671. 二叉树中第二小的节点

    • 230. 二叉搜索树中第K小的元素 - 二叉搜索树中序遍历是升序
    展开全文
  • 二叉树的前序遍历、中序遍历和后序遍历之间还原二叉树1、概念(1)前序遍历 a、访问根节点;b、前序遍历左子树;c、前序遍历右子树。(2)中序遍历 a、中序遍历左子树;b、访问根节点;c、中序遍历右子树。(3)...

    二叉树的前序遍历、中序遍历和后序遍历之间还原二叉树

    1、概念

    (1)前序遍历

          a、访问根节点;b、前序遍历左子树;c、前序遍历右子树。

    (2)中序遍历

          a、中序遍历左子树;b、访问根节点;c、中序遍历右子树。

    (3)后序遍历

          a、后序遍历左子树;b、后续遍历右子树;c、访问根节点。

    2、前序遍历和中序遍历还原二叉树

    思想如下:

        a、根据前序遍历结果,第一个元素为二叉树的根结点;

        b、观察中序遍历结果,根结点左侧的为左子树,若左子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;根结点右侧的为右子树,若右子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;

        c、上面的过程是递归的。先找到当前树的根结点,然后划分为左右子树,再进入左子树重复上面的过程,最后进入右子树重复上面的过程,最终还原一棵树。

    例:

        已知前序遍历:ABDHIEJKCFLMGNO

               中序遍历:HDIBJEKALFMCNGO


    按照上述步骤先画出二叉树,然后在进行求解后序遍历结果。结果为:HIDJKEBLMFNOGCA

    练习:

    1、前序遍历:GDAFEMHZ

          中序遍历:ADEFGHMZ

        求得后序遍历结果为:AEFDHZMG

    2序遍历:ADCEFGHB

          中序遍历:CDFEGHAB

        求得后序遍历结果为:CFHGEDBA

    3、中序遍历和后序遍历还原二叉树

    思想如下:

        a、根据后序遍历结果,最后一个元素为二叉树的根结点;

        b、观察中序遍历结果,其中根结点左侧为左子树,若左子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;其中根结点右侧为右子树,若右子树根结点前(后)再无任何元素,则左(右)子树的左分支为空;

        c、上面的过程是递归的。先根据后序遍历结果找根结点,根结点左侧为左子树,右侧为右子树,再进入左子树重复上面的过程,最后进入右子树重复上面的过程,最终还原一棵树。

    例:

        已知

    中序遍历:HDIBJEKALFMCNGO

    后序遍历:

    HIDJKEBLMFNOGCA

             

    按照上述步骤先画出二叉树,然后在进行求解前序遍历结果。结果为:

    ABDHIEJKCFLMGNO

    练习:可参考前序遍历和中序遍历的练习

    4、前序遍历和后序遍历还原二叉树

    已知前序和中序,后序和中序遍历序列之后,可以唯一确定一棵二叉树。但是,只知道前序和后序遍历序列,是无法知道哪个结点是左子树还算右子树。



    展开全文
  • 主要介绍了C#使用前序遍历、中序遍历和后序遍历打印二叉树的方法,涉及C#遍历二叉树的相关技巧,需要的朋友可以参考下
  • LDR--中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面) LRD--后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面) 需要注意几点: 根是相对...

    0. 写在最前面

    希望大家收藏:

    本文持续更新地址:https://haoqchen.site/2018/05/23/go-through-binary-tree/

        复习到二叉树,看到网上诸多博客文章各种绕,记得头晕。个人觉得数学、算法这些东西都是可以更直观简洁地表示,然后被记住的,并不需要靠死记硬背。

    本文的程序基本来源于《大话数据结构》,个人感觉是一本非常好的书,推荐去看。

    1. 为什么叫前序、后序、中序?

        一棵二叉树由根结点、左子树和右子树三部分组成,若规定 D、L、R 分别代表遍历根结点、遍历左子树、遍历右子树,则二叉树的遍历方式有 6 种:DLR、DRL、LDR、LRD、RDL、RLD。由于先遍历左子树和先遍历右子树在算法设计上没有本质区别,所以,只讨论三种方式:

    DLR--前序遍历(根在前,从左往右,一棵树的根永远在左子树前面,左子树又永远在右子树前面 )

    LDR--中序遍历(根在中,从左往右,一棵树的左子树永远在根前面,根永远在右子树前面)

    LRD--后序遍历(根在后,从左往右,一棵树的左子树永远在右子树前面,右子树永远在根前面)

    需要注意几点:

    1. 根是相对的,对于整棵树而言只有一个根,但对于每棵子树而言,又有自己的根。比如对于下面三个图,对于整棵树而言,A是根,A分别在最前面、中间、后面被遍历到。而对于D,它是G和H的根,对于D、G、H这棵小树而言,顺序分别是DGH、GDH、GHD;对于C,它是E和F的根,三种排序的顺序分别为: CEF、ECF、EFC。是不是根上面的DLR、LDR、LRD一模一样呢~~
    2. 整棵树的起点,就如上面所说的,从A开始,前序遍历的话,一棵树的根永远在左子树前面,左子树又永远在右子树前面,你就找他的起点好了。
    3. 二叉树结点的先根序列、中根序列和后根序列中,所有叶子结点的先后顺序一样
    4. 建议看看文末第3个参考有趣详细的推导

                      前序遍历(DLR)                                 中序遍历(LDR)                             后序遍历(LRD)

     

    2. 算法上的前中后序实现

    除了下面的递归实现,还有一种使用栈的非递归实现。因为递归实现比较简单,且容易关联到前中后,所以

    typedef struct TreeNode
    {
        int data;
        TreeNode * left;
        TreeNode * right;
        TreeNode * parent;
    }TreeNode;
     
    void pre_order(TreeNode * Node)//前序遍历递归算法
    {
        if(Node == NULL)
            return;
        printf("%d ", Node->data);//显示节点数据,可以更改为其他操作。在前面
        pre_order(Node->left);
        pre_order(Node->right);
    }
    void middle_order(TreeNode *Node)//中序遍历递归算法
    {
        if(Node == NULL)
            return;
        middle_order(Node->left);
        printf("%d ", Node->data);//在中间
        middle_order(Node->right);
    }
    void post_order(TreeNode *Node)//后序遍历递归算法
    {
        if(Node == NULL)
            return; 
        post_order(Node->left);
        post_order(Node->right);
        printf("%d ", Node->data);//在最后
    }

    3. 层序遍历

      层序遍历嘛,就是按层,从上到下,从左到右遍历,这个没啥好说的。

    参考

    1.《大话数据结构》

    2.https://cnbin.github.io/blog/2016/01/05/er-cha-shu-de-bian-li/

    3.https://blog.csdn.net/soundwave_/article/details/53120766

     

     

     

    展开全文
  • 主要介绍了Python二叉树的遍历操作,结合实例形式分析了Python针对二叉树的前序遍历,中序遍历,后序遍历,层序遍历等相关操作实现技巧,需要的朋友可以参考下
  • 二叉树的遍历方式主要有:先序遍历、中序遍历、后序遍历、层次遍历。先序、中序、后序其实指的是父节点被访问的次序。若在遍历过程中,父节点先于它的子节点被访问,就是先序遍历;父节点被访问的次序位于左右孩子...

    概述

    二叉树的遍历是一个很常见的问题。二叉树的遍历方式主要有:先序遍历、中序遍历、后序遍历、层次遍历。先序、中序、后序其实指的是父节点被访问的次序。若在遍历过程中,父节点先于它的子节点被访问,就是先序遍历;父节点被访问的次序位于左右孩子节点之间,就是中序遍历;访问完左右孩子节点之后再访问父节点,就是后序遍历。不论是先序遍历、中序遍历还是后序遍历,左右孩子节点的相对访问次序是不变的,总是先访问左孩子节点,再访问右孩子节点。而层次遍历,就是按照从上到下、从左向右的顺序访问二叉树的每个节点。

    在介绍遍历算法之前,先定义一个二叉树的结构体。使用的是 C++ 语言。

    //filename: BinTreeNode.h
    template <typename T> struct BinTreeNode {
        T data; //数据域
        BinTreeNode * LeftChild; //左孩子节点指针
        BinTreeNode * RightChild; //右孩子节点指针
        BinTreeNode * parent; //父节点指针
    };
    

    先序遍历

    递归

    使用递归,很容易写出一个遍历算法。代码如下:

    //filename: BinTreeNode.h
    template <typename T>
    void travPre_R(BinTreeNode<T> * root) {//二叉树先序遍历算法(递归版)
        if (!root) return;
        cout << root->data;
        travPre_R(root->LeftChild);
        travPre_R(root->RightChild);
    }
    

    迭代

    在之前的文章中,我不止一次地说过,递归是很耗费计算机资源的,所以我们在写程序的时候要尽量避免使用递归。幸运的是,绝大部分递归的代码都有相应的迭代版本。那么我们就试着将上述递归代码改写成迭代的版本。改写之后,代码如下:

    //filename: BinTreeNode.h
    template <typename T>
    void travPre_I1(BinTreeNode<T> * root) {//二叉树先序遍历算法(迭代版#1)
        Stack<BinTreeNode<T>*> s; //辅助栈
        if (root) //如果根节点不为空
            s.push(root); //则令根节点入栈
        while (!s.empty()) { //在栈变空之前反复循环
            root = s.pop(); cout << root->data; //弹出并访问当前节点
    
            //下面左右孩子的顺序不能颠倒,必须先让右孩子先入栈,再让左孩子入栈。
            if (root->RightChild)
                s.push(root->RightChild); //右孩子先入后出
            if (root->LeftChild)
                s.push(root->LeftChild); //左孩子后入先出
        }
    }
    

    下面我们通过一个实例来了解一下该迭代版本是如何工作的。

    PS:黑色的元素表示已经被弹出并访问过。

    结合代码,该二叉树的先序遍历过程如下:

    1. 初始化一个空栈。
    2. 根节点入栈,此时将 a 入栈。
    3. 循环开始,弹出并访问栈顶元素,此时栈顶元素是 a。
    4. 如果 a 有右孩子,则将其右孩子节点入栈;如果 a 有左孩子,则将其左孩子节点入栈。此时栈中有 b、c 两个元素。
    5. 这时进入下一轮循环。弹出并访问栈顶元素,此时栈顶元素是 b。经检查,b 没有右孩子,也没有左孩子,进入下一轮循环。
    6. 弹出并访问栈顶元素,此时栈顶元素是 c。c 的右孩子是 f,左孩子是 d,故分别将 d、f 入栈。进入下一轮循环。
    7. 此时栈中的元素是 d、f。
    8. 弹出并访问栈顶元素,此时栈顶元素是 d。d 的右孩子是 e,d 没有左孩子,故将 e 入栈。进入下一轮循环。
    9. 此时栈中的元素是 e、f。
    10. 弹出并访问栈顶元素,此时栈顶元素是 e。e 没有左右孩子,进入下一轮循环。
    11. 弹出并访问栈顶元素,此时栈顶元素是 f。f 没有左右孩子,进入下一轮循环。
    12. 此时栈为空,退出循环。遍历结束。

    这个迭代的遍历算法非常简明,但是很遗憾,这种算法并不容易推广到我们接下来要研究的中序遍历和后序遍历。因此我问需要寻找另一种策略。

    第 2 种迭代方式

    我们来看一个规模更大、更具一般性的二叉树:

    这个二叉树的先序遍历序列是:idcabhfeglkjnmpo,也就是遵循了下图所示的顺序:

    再进一步,我们把二叉树抽象成下面这个样子,


    L_0 ~ L_d 是二叉树的左侧链上的节点, R_0 ~ R_d 分别是 L_0 ~ L_d 的右孩子,T_0 ~ T_d 分别是 L_0 ~ L_d 的右子树。不难发现,二叉树的先序遍历就是先自上而下访问左侧链上的节点,再自下而上访问左侧链上的节点的右子树。而我们的遍历算法,就是根据这样一个思路来进行设计。

    首先需要实现一个子方法,就是访问二叉树左侧链上的节点:

    //从当前节点出发,沿左分支不断深入,直至没有左分支的节点;沿途节点遇到后立即访问
    template <typename T> //元素类型、操作器
    static void visitAlongLeftBranch ( BinTreeNode<T>* x, Stack<BinTreeNode<T>*>& S ) {
       while ( x ) {
          cout << x->data; //访问当前节点
          if( x->RightChild )
               S.push ( x->RightChild ); //右孩子入栈暂存(可优化:通过判断,避免空的右孩子入栈)
          x = x->LeftChild;  //沿左分支深入一层
       }
    }
    

    然后是主方法,在主方法中,通过迭代,不断地调用上面这个子方法,从而实现完整的二叉树先序遍历。

    template <typename T> //元素类型、操作器
    void travPre_I2 ( BinTreeNode<T>* root) { //二叉树先序遍历算法(迭代版#2)
       Stack<BinTreeNode<T>*> S; //辅助栈
       while ( true ) {
          visitAlongLeftBranch ( root, S ); //从当前节点出发,逐批访问
          if ( S.empty() ) break; //直到栈空
          root = S.pop(); //弹出下一批的起点
       }
    }
    

    中序遍历

    递归

    与先序遍历类似,递归版的中序遍历算法很容易实现,代码如下:

    template <typename T>
    void travIn_R(BinTreeNode<T> * root) {//二叉树先序遍历算法(递归版)
        if (!root)
            return;
        travPre_R(root->LeftChild);
        cout << root->data;
        travPre_R(root->RightChild);
    }
    

    递归代码不仅容易实现,也很好理解,这里不再做过多解释。

    迭代

    参照迭代式先序遍历版本 2 的思路,在宏观上,我们可以将中序遍历的顺序抽象为,先访问二叉树的左侧链上的最底部的节点,然后访问该节点的右子树(如果有的话),然后访问该节点的父节点,然后访问该节点的父节点的右子树(如果有的话)……直至全部节点被访问完毕。如下图所示:

    按照以上思路,可以实现迭代版中序遍历算法如下:

    template <typename T> //从当前节点出发,沿左分支不断深入,直至没有左分支的节点
    static void goAlongLeftBranch ( BinTreeNode<T> * x, Stack<BinTreeNode<T> * >& S ) {
        while (x) { S.push(x); x = x->LeftChild; } //当前节点入栈后随即向左侧分支深入,迭代直到无左孩子
    }
    

    template <typename T> //元素类型、操作器
    void travIn_I(BinTreeNode<T> root) {//二叉树先序遍历算法(迭代版)
    Stack<BinTreeNode<T> > S; //辅助栈
    while ( true ) {
    goAlongLeftBranch ( root, S ); //从当前节点出发,逐批入栈
    if ( S.empty() ) break; //直至所有节点处理完毕
    root = S.pop();
    cout << root->data; //弹出栈顶节点并访问之
    root = root->RightChild; //转向右子树
    }
    }

    也可以对代码稍加改进,将这两个方法写成一个方法:

    template <typename T> //元素类型
    void travIn_I2 ( BinTreeNode<T> root ) { //二叉树中序遍历算法(迭代版#2)
    Stack<BinTreeNode<T>> S; //辅助栈
    while ( true )
    if ( root ) {
    S.push ( root ); //根节点进栈
    root = root->LeftChild; //深入遍历左子树
    } else if ( !S.empty() ) {
    root = S.pop(); //尚未访问的最低祖先节点退栈
    cout << root->data; //访问该祖先节点
    root = root->RightChild; //遍历祖先的右子树
    } else
    break; //遍历完成
    }

    后序遍历

    递归

    与前两个一样,二叉树的后序遍历算法可以很容易地用递归的方式实现。

    template <typename T>
    void travPost_R(BinTreeNode<T> root) {//二叉树先序遍历算法(递归版)
    if (!root)
    return;
    travPost_R(root->LeftChild);
    travPost_R(root->RightChild);
    cout << root->data;
    }

    迭代

    但是要想用迭代的方式实现后序遍历算法,则有一定的难度,因为左、右子树的递归遍历均严格地不属于尾递归。不过,仍可继续套用此前的思路和技巧,考虑一下,后序遍历中,首先访问的是哪个节点?答案就是二叉树的最高最左侧的叶子节点。

    由于最高最左侧的叶子节点 V 可能是左孩子节点,也可能是右孩子节点,所以 V 与其父节点之间的联接用竖直的线表示。考查联接于 V 与树根之间的唯一通路(以粗线示意)。与先序与中序遍历类似地,自底而上地沿着该通路,整个后序遍历序列也可以分解为若干个片段。每一片段,分别起始于通路上的一个节点,并包括三步:访问当前节点,遍历以其右兄弟(若存在)为根的子树,以及向上回溯至其父亲节点(若存在)并转入下一片段。

    基于以上理解,即可写出迭代式后序遍历算法。

    template <typename T> //在以S栈顶节点为根的子树中,找到最高左侧叶节点
    static void gotoHLVFL ( Stack<BinTreeNode<T>>& S ) { //沿途所遇节点依次入栈
    while ( BinTreeNode<T>* x = S.top() ) //自顶而下,反复检查当前节点(即栈顶)
    if ( x->LeftChild ) { //尽可能向左
    if ( x->RightChild ) S.push ( x->RightChild ); //若有右孩子,优先入栈
    S.push ( x->LeftChild ); //然后才转至左孩子
    } else //实不得已
    S.push ( x->RightChild ); //才向右
    S.pop(); //返回之前,弹出栈顶的空节点
    }

    template <typename T>
    void travPost_I ( BinTreeNode<T> root ) { //二叉树的后序遍历(迭代版)
    Stack<BinTreeNode<T>> S; //辅助栈
    if ( root ) S.push ( root ); //根节点入栈
    while ( !S.empty() ) {
    if ( S.top() != root->parent ) //若栈顶非当前节点之父(则必为其右兄),此时需
    gotoHLVFL ( S ); //在以其右兄为根之子树中,找到HLVFL(相当于递归深入其中)
    root = S.pop(); cout << root->data; //弹出栈顶(即前一节点之后继),并访问之
    }
    }

    层次遍历

    在文章开头我们已经对层次遍历做了介绍,层次遍历严格按照自上而下、自左向右的顺序访问树的节点。所以我们需要用队列作为辅助,具体代码如下:

    template <typename T> //元素类型
    void travLevel ( BinTreeNode<T> root ) { //二叉树层次遍历算法
    Queue<BinTreeNode<T>> Q; //辅助队列
    Q.enqueue ( root ); //根节点入队
    while ( !Q.empty() ) { //在队列再次变空之前,反复迭代
    BinTreeNode<T>* x = Q.dequeue(); cout << x->data; //取出队首节点并访问之
    if ( x->LeftChild ) Q.enqueue ( x->LeftChild ); //左孩子入队
    if ( x->RightChild ) Q.enqueue ( x->RightChild ); //右孩子入队
    }
    }

    好了,以上就是二叉树的几种常见的遍历方式。

    展开全文
  • 已知前序遍历,中序遍历求后序遍历代码
  • 根据前序遍历和中序遍历求后序遍历

    千次阅读 多人点赞 2019-07-19 21:29:59
    假设某二叉树的先序遍历序列是abdgcefh,中序遍历序列是dgbaechf,画出二叉树,并给出其后序遍历序列。 分析过程: 以下面的例题为例进行讲解: 已知一棵二叉树的先序遍历序列和中序遍历序列分别是abdgcefh、...
  • 数据结构二叉树链式结构的前序遍历,中序遍历,后序遍历用递归的方法,层级遍历采用队列结构
  • 先来看看前序遍历、中序遍历与后序遍历原理图: 根据树的前序遍历和中序遍历构造树并输出后序遍历代码如下: <?php class BinaryTreeNode{ public $m_value; public $m_left; public $m_right; } function ...
  • 当我们有一个 先序遍历序列:1,3,7,9,5,11 中序遍历序列:9,7,3,1,5,11 我们可以很轻松的用笔写出对应的二叉树。...我们确定数字1为根节点,然后根据中序遍历的遍历顺序确定,中序遍历序列中数字1的左边
  • 已知中序遍历和后序遍历,求前序遍历。有比较详尽的中文注释。
  • VC6 0 链式二叉树的中序创建 递归中序遍历 非递归堆栈中序遍历 中序销毁 求树的深度
  • 数据结构C++二叉链表的先序遍历、中序遍历和后序遍历实现
  • 中序遍历二叉排序树

    2018-06-30 21:06:55
    中序遍历二叉排序树 输入一整数序列,建立二叉排序树,然后中序遍历。 输入说明 输入第一行为整数的个数n,第二行是具体的n个整数。 输出说明 建立二叉排序树,然后输出中序遍历的结果。 输入样例 5 1 6 5 9 8 ...
  • 本文实例讲述了Python利用前序和中序遍历结果重建二叉树的方法。分享给大家供大家参考,具体如下: 题目:输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含...
  • 本文实例讲述了C++基于先序、中序遍历结果重建二叉树的方法。分享给大家供大家参考,具体如下: 题目: 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树。假设输入的前序遍历和中序遍历的结果中都不含...
  • 前序遍历 + 中序遍历 --------------- 可以确定唯一一棵二叉树 后序遍历 + 中序遍历 --------------- 可以确定唯一一颗二叉树 前序遍历 + 中序遍历 --------------- 不能唯一确定 !因为先序后序遍历都是确定根的...
  • 二叉树的中序遍历 题目描述: 解题思路: 第一种:递归。又是递归,可以发现很多题都可以用到递归的思路…。二叉树的中序遍历,这里不太了解的可以看看这个博客:二叉树遍历,总结了二叉树的所有遍历情况。这道题所...
  • 数据结构算法及应用 上机作业 谦虚中序遍历顺序&中序后续遍历顺序,还原二叉树并输出
  • 二叉树的遍历规则主要有三种:前序遍历,中序遍历,后序遍历。它们是根据访问根节点的先后顺序来划分的。 前序遍历: 1.访问根节点 2.前序遍历左子树 3.右序遍历右子树 中序遍历: 1.中序遍历左子树 2.访问根节点...
  • 主要介绍了Python实现输入二叉树的先序和中序遍历,再输出后序遍历操作,涉及Python基于先序遍历和中序遍历构造二叉树,再后序遍历输出相关操作技巧,需要的朋友可以参考下
  • 前序遍历+中序遍历=后序遍历 中序遍历+后序遍历=前序遍历
  • Java二叉树中序遍历

    2015-05-18 19:34:17
    一个简单的课程设计,使用Java来实现二叉树的中序遍历
  • Java实现 LeetCode 94 二叉树的中序遍历

    万次阅读 多人点赞 2020-02-17 21:48:31
    94. 二叉树的中序遍历 给定一个二叉树,返回它的中序 遍历。 示例: 输入: [1,null,2,3] 1 2 / 3 输出: [1,3,2] 进阶: 递归算法很简单,你可以通过迭代算法完成吗? /** * Definition for a binary tree node. * ...
  • 中序遍历为:1234567 后序遍历为:2315764 由基本思想,先找到总树的根节点就为后序遍历的最后一个点。即4为Root 然后由找到的根节点 在中序遍历中找到左子树的中序遍历结果为123。 在后序遍历中找到左子树的后序...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 125,952
精华内容 50,380
关键字:

中序遍历