遍历一个数据结构,也即逐一地处理(可读可写)其中所有元素。

  • 二叉树的遍历:一棵二叉树可以看作一个状态空间:根节点(入口)对应状态空间的初始状态,父子结点连接对应状态的邻接关系。以这种观点,一次二叉树的遍历就是一次覆盖整个状态空间的搜索

1. 深度优先与广度优先

按深度优先的方式遍历一棵二叉树,需要做三件事(可能需要处理其中的数据):

  • 遍历左子树(L);
  • 遍历根节点(D);
  • 遍历右子树(R);

全排列的话,A33=6A_3^3=6,但这里一般假定先处理左子树,后处理右子树,这样,根据根节点遍历的先后顺序,仅可得到三种遍历方式(先中后说的都是根节点的遍历相对顺序)。

由于二叉树的子树也是二叉树,将一种具体的遍历顺序(先中后)方式继续运用到子树的遍历中,就形成了一种二叉树的统一方法。

宽度优先(层次遍历)是按路径长度(自己到自己,路径长度为 0)由近到远地访问节点。对二叉树做这种遍历,也就是按二叉树的层次逐层访问树中各结点。与状态空间搜索的情况一样,这种遍历不能写成一个递归的过程

在宽度优先遍历中规定了逐层访问,并未规定同一层结点的访问顺序。但从算法的角度,必须规定一个顺序,常见的是在每一层里都从左到右逐个访问(从右到左,也是需要使用一个队列,只不过进队的顺序是从右子节点,左子节点)。实现这一算法需要一个队列作为缓存。

2. 二叉树的遍历:递归实现

  • 先序:

    template<typename T, typename VST>
    void travPreorder_R(BinNode<T>* x, VST& visit){
    if (!x) return;
    visit(x->data);
    if (HasLChild(x))
    travPreorder_R(x->lChid, visit);
    if (HasRChild(x))
    travPreorder_R(x->rChild, visit);
    }
  • 中序:

    template<typename T, typename VST>
    void travInorder_R(BinNode<T>* x, VST& visit){if (!x) return;if (HasLChild(x))travPreorder_R(x->lChid, visit);visit(x->data);if (HasRChild(x))travPreorder_R(x->rChild, visit);
    }
    
  • 后序:

    template<typename T, typename VST>
    void travInorder_R(BinNode<T>* x, VST& visit){if (!x) return;if (HasLChild(x))travPreorder_R(x->lChid, visit);if (HasRChild(x))travPreorder_R(x->rChild, visit);visit(x->data);
    }

3. 二叉树的遍历 —— 迭代实现

  • 先序,思路,先一路向左(同时把右子树保存在栈里),再把栈中的右子树出栈,

    // 辅助函数
    template <typename T, typename VST>
    void visitAlongLeftBranch(BinNode<T>* x, VST& visit, Stack<BinNode<T>*> S){while (x){visit(x->data);S.push(x->rChild);x = x->lChild;}
    }template <typename T, typename VST>
    void travPreorder_I1(BinNode<T>* x, VST& visit){Stack<BinNode<T>*> S;while (true){visitAlongLeftBranch(x, visit, S);if (S.empty())break;x = S.pop();}
    }
  • 后序,思考的起点依然是,首先访问的结点是哪一个?(HLVFL,Highest Leaf Visual From Left)

    template <typename T>
    void gotoHLVFL(Stack<BinNode<T>*> S){while (BinNode<T>* x = S.top()){     // 循环退出时,一定是 x 为 NULL 了,也即 S.top() 栈顶元素为空if (HasLChild(x)){if (HasRChild(x)){S.push(x->rChild);}S.push(x->lChild);} else {S.push(x->rChild);}}S.pop();         // 弹出栈顶的空元素;
    }template <typename T, typename VST>
    void travPostorder_I(BinNode<T>* x, VST& visit){Stack<BinNode<T>*> S;if (x) S.push(x);while (!S.empty()){if (S.top() != x.parent){gotoHLVFL(S);}x = S.pop();visit(x->data);}
    }

二叉树的遍历(先序/中序/后序,递归/迭代)与搜索相关推荐

  1. Python__数据结构与算法——树、二叉树(实现先、中、后序遍历)

    目录 一.树 二.二叉树 树和前面所讲的表.堆栈和队列等这些线性数据结构不同,树不是线性的.在处理较多数据时,使用线性结构较慢,而使用树结构则可以提高处理速度.不过,相对于线性的表.堆栈和队列等线性数 ...

  2. java中二叉树_Java工程师面试1000题224-递归非递归实现二叉树前、中、后序遍历...

    224.使用递归和非递归实现二叉树的前.中.后序遍历 使用递归来实现二叉树的前.中.后序遍历比较简单,直接给出代码,我们重点讨论非递归的实现. class Node { public int valu ...

  3. 由序列确定二叉树:前序序列和中序序列构造二叉树 后序序列和中序序列构造二叉树 层次遍历序列和中序遍历序列构造二叉树 代码实现(c语言)

    下面三种序列可以唯一的构造唯一的一棵二叉树: 前序序列和中序序列构造二叉树 后序序列和中序序列构造二叉树 层次遍历序列和中序遍历序列构造二叉树 #include<stdio.h> #inc ...

  4. 二叉树的前、中、后序遍历

    所谓二叉树遍历是按某种特定规则,依次对二叉树中的节点进行相应的操作,并且每个节点只操作一次.访问结点所做的操作依赖于具体的应用问题. 遍历是二叉树上最重要的运算之一,也是二叉树进行其它运算的基础. 二 ...

  5. 非递归先、中、后序遍历二叉树(C语言)

    文章目录 前言 一.二叉树非递归遍历算法 1.先序遍历 2.中序遍历 3.后序遍历 二.完整程序 三.运行结果实例 前言 本程序采用C语言编写,栈和二叉树的基本操作函数基于严蔚敏老师的<数据结构 ...

  6. 二叉树前、中、后线索化及对应前、中、后序线索化遍历

    二叉树前中后线索化及对应前中后序线索化遍历(图解) 二叉树线索化都是套路,会一种另外两种只是稍微修改一下代码 值得一提的是后序线索化输出,逆序思维将后序线索化看成前序,采用"前序线索化输出& ...

  7. 二叉树遍历方法——前、中、后序遍历(图解)

    目录 一.前序遍历 (1)递归版本 (2)非递归版本 二.中序遍历 (1)递归版本 (2)非递归版本 三.后序遍历 (1)递归版本 (2)非递归版本 四.总结 五.测试程序 六.程序输出 二叉树的遍历 ...

  8. PAT甲级1020 Tree Traversals:[C++题解]树的遍历、由中序序列和后序序列递归建树

    文章目录 题目分析 题目链接 题目分析 题意重述:给定一棵二叉树的后序遍历序列和中序遍历序列,让求层次遍历的序列. 分析: 后序遍历:先 左子树.右子树 ,最后再遍历根结点. 中序遍历:先左子树,再根 ...

  9. 7-10 先序序列创建二叉树,输出先序序列、中序序列、后序序列并输出叶子结点数 (10 分)

    7-10 先序序列创建二叉树,输出先序序列.中序序列.后序序列并输出叶子结点数 (10 分) 对于给定的二叉树,输出其先序序列.中序序列.后序序列并输出叶子结点数. 输入格式: 二叉树的先序遍历序列. ...

  10. 二叉树的构造(前序+中序)---(后序 + 中序)

    二叉树的构造(前序+中序)-(后序 + 中序) 思路:要对前序+中序(后序+中序)的构建树的动态过程要了解,思路比较简单,在了解了这个过程之后,理解下面代码就容易了. 过程 参考图: 前序 + 中序: ...

最新文章

  1. java高级之Io流
  2. android ImageButton设置背景图片无法显示
  3. C++三角函数用法错误error C2668: 'tan' : ambiguous call to overloaded function原因及解决方法
  4. wordcloud里面设置mask加载不出来词频_一条龙搞定情感分析:文本预处理、加载词向量、搭建RNN
  5. 查询SQLSERVER执行过的SQL记录(历史查询记录)
  6. linux下的C语言开发(gdb调试)
  7. mysql建表影响效率_关于MySQL建表对DML的影响【转】
  8. adobe出的cookbook
  9. 长沙北大青鸟:北大青鸟培训学士后课程让大学生重回就业春天
  10. 安装MPICH并运行第一行代码
  11. 联合循环——30 正式倒送电
  12. 计算机网络技术评估与备选方案,创业学复习提纲
  13. 语音识别/合成开源项目
  14. C++命名空间中类声明、成员函数声明和函数模板
  15. 超详细软件工程黑书思维导图(从第一章到第八章)
  16. 偶尔也需要强烈的孤独
  17. 趣味数学(各大经典数学问题)
  18. 【等保小知识】等保3.0就是等保三级吗?
  19. Phab2 Pro体验 Tango技术简介
  20. GDAL读取Jpeg2000格式图像

热门文章

  1. python def函数报错详解_JSer 快速入门 Python 之函数详解
  2. python 反爬策略_如何应对网站反爬虫策略?如何高效地爬大量数据?
  3. git忽略文件或者文件夹
  4. Python之 面向对象封装案例
  5. python: for循环时列表长度改变,会发生什么?
  6. Object类的使用,包装类的使用
  7. python选择语句是什么语句_Python语言中的三种选择语句
  8. 为什么派生的子类报错不能实例化抽象类_C# 接口与抽象类实例分析
  9. 如何用命令行运行python程序_如何使用运行python代码命令行.exe从C应用程序?
  10. Softmax Derivation