博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
二叉树的遍历(先序/中序/后序,递归/迭代)与搜索
阅读量:5329 次
发布时间:2019-06-14

本文共 2610 字,大约阅读时间需要 8 分钟。

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

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

1. 深度优先与广度优先

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

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

全排列的话,A33=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
    void travInorder_R(BinNode
    * 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
    void travInorder_R(BinNode
    * 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 
    void visitAlongLeftBranch(BinNode
    * x, VST& visit, Stack
    *> S){ while (x){ visit(x->data); S.push(x->rChild); x = x->lChild; }}template
    void travPreorder_I1(BinNode
    * x, VST& visit){ Stack
    *> S; while (true){ visitAlongLeftBranch(x, visit, S); if (S.empty()) break; x = S.pop(); }}
  • 后序,思考的起点依然是,首先访问的结点是哪一个?(HLVFL,Highest Leaf Visual From Left)

    template 
    void gotoHLVFL(Stack
    *> S){ while (BinNode
    * 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
    void travPostorder_I(BinNode
    * x, VST& visit){ Stack
    *> S; if (x) S.push(x); while (!S.empty()){ if (S.top() != x.parent){ gotoHLVFL(S); } x = S.pop(); visit(x->data); }}

转载于:https://www.cnblogs.com/mtcnn/p/9424165.html

你可能感兴趣的文章
DCDC(4.5V to 23V -3.3V)
查看>>
kettle导数到user_用于left join_20160928
查看>>
activity 保存数据
查看>>
typescript深copy和浅copy
查看>>
linux下的静态库与动态库详解
查看>>
hbuilder调底层运用,多张图片上传
查看>>
较快的maven的settings.xml文件
查看>>
Git之初体验 持续更新
查看>>
随手练——HDU 5015 矩阵快速幂
查看>>
Maven之setting.xml配置文件详解
查看>>
SDK目录结构
查看>>
malloc() & free()
查看>>
HDU 2063 过山车
查看>>
高精度1--加法
查看>>
String比较
查看>>
Django之Models
查看>>
CSS 透明度级别 及 背景透明
查看>>
Linux 的 date 日期的使用
查看>>
PHP zip压缩文件及解压
查看>>
SOAP web service用AFNetWorking实现请求
查看>>