非递归的遍历需要使用栈保存当前不输出的结点,并且三种遍历顺序步骤有所不同。

中序遍历

1.查看其当前结点是否为空:

若非空则将当前结点入栈,指针指向其左孩子;

若当前结点为空,说明上一个入栈的结点没有左孩子,将上一个结点出栈打印;

2.之后指针指向其右孩子

3.循环步骤1、2,直到栈为空(所有结点都遍历完出栈了)

void NiceInOrder(BTNode*p)
{if (p == NULL)return;stack<BTNode*>st;while (!st.empty()||p!=NULL){while (p != NULL){st.push(p);p = p->lchild;}p = st.top();st.pop();printf("%c ", p->data);p = p->rchild;}printf("\n");
}

后序遍历

后序遍历因为先输出左右子树再输出根(14行),这个过程中需要通过根结点,所以需要有一个值来记录该根结点的左右子树是否都已经遍历(5行)。

要注意打印之后指针要指向空(19行),若当前树是某棵树的左子树,下次循环时为空则不在遍历这棵树了,否则程序陷入死循环。

void NicePastOrder(BTNode* p)
{if (p == NULL)return;stack<BTNode*>st;BTNode* tag = NULL;//标记,指向遍历完右孩子的结点while (!st.empty() || p != NULL){while (p != NULL)//遍历左子树{st.push(p);p = p->lchild;}p = st.top(); if (p->rchild == NULL || p->rchild == tag)//右子树为空或遍历完,打印根{st.pop();printf("%c ", p->data);tag = p;//指向遍历完的根p = NULL;//表示左孩子已经遍历完了}else//否则指向右子树继续遍历{p = p->rchild;}}printf("\n");
}

先序遍历

先序遍历是根左右的顺序,先入根结点,出根;

之后入栈顶的右、左孩子(因为栈先进后出,所以要先入右孩子)

void NicePreOrder(BTNode* p)
{if (p == NULL)return;stack<BTNode*>st;st.push(p);while (!st.empty()){p = st.top();printf("%c ",p->data);st.pop();//先右后左入栈,先左后右出栈if (p->rchild != NULL){st.push(p->rchild);}if (p->lchild != NULL){st.push(p->lchild);}}
}

层次遍历

层次遍历需要使用队列

步骤:

1.入根结点及其左右孩子;

2.出队头元素,入队头结点的左右孩子(不为空)

3.若队列为空则遍历完该树

void LevelOrder(BTNode* p)
{if (p == NULL)return;queue<BTNode*>qu;qu.push(p);while (!qu.empty()){p = qu.front();printf("%c ",p->data);qu.pop();if(p->lchild!=NULL)qu.push(p->lchild);if (p->rchild != NULL)qu.push(p->rchild);}printf("\n");
}

另一种非递归遍历要将每个结点出栈的次数记下:定义一个结构体

struct StkNode
{BTNode* pnode;int popnum;//出栈次数
};

后序遍历:每个结点都需要三次出栈,访问完它的左右根和自己

结点第一次入栈时出栈次数为0

当栈不为空,栈顶元素出栈

若出栈时popnum==3(第三次出栈,说明左右子树都遍历了),输出该结点;

若出栈时popnum==1且其左孩子不为空,则再将其入栈,并入其左孩子。

若出栈时popnum==2且其右孩子不为空,则再将其入栈,并入其右孩子;

void NicePastOrder_2(BTNode* p)
{if (p = NULL)return;stack<StkNode>st;st.push(StkNode{ p,0 });while (!st.empty()){StkNode node = st.top(); st.pop();if (++node.popnum == 3)//左右子树都访问了{printf("%c ", node.pnode->data);}else{st.push(node);if (node.popnum == 1 &&p->lchild!=NULL){st.push(StkNode{node.pnode->lchild,0});}else if (node.popnum == 2 && p->rchild != NULL){st.push(StkNode{ node.pnode->rchild,0 });}}}printf("\n");
}

中序遍历将顺序改一下,前序遍历就不需要这样了,第一种方法比较方便。

【树】二叉树的两种非递归遍历方法相关推荐

  1. 实现二叉树的三种非递归遍历算法

    [问题描述] 编写程序,实现二叉树的三种非递归遍历算法:先序非递归,中序非递归,后序非递归. [输入形式] 输入建树序列. [输出形式] 输出三种遍历序列. [样例输入] A B C # # # # ...

  2. 对于二叉树三种非递归遍历方式的理解

    利用栈实现二叉树的先序,中序,后序遍历的非递归操作 栈是一种先进后出的数据结构,其本质应是记录作用,支撑回溯(即按原路线返回):因此,基于其的二叉树遍历操作深刻的体现了其特性: 若后续的输入和其前面的 ...

  3. 二叉树的后序非递归遍历(巧妙思想)

    大家都知道二叉树的前序非递归遍历非常好写: //二叉树的结构 public class TreeNode {TreeNode left;TreeNode right;int val;TreeNode( ...

  4. 二叉树的中序非递归遍历

    二叉树的中序非递归遍历 中序遍历的非递归算法描述如下: 从根节点开始检索,如果当前节点不为空,则将当前节点入栈,让当前节点成为其左孩子节点,再继续上一步的操作 加入当前节点为空了,说明其父节点已经没有 ...

  5. 完全二叉树的JAVA实现(以及非递归遍历方法)

    一个用于实现初始化指定个数的完全二叉树,以及两个非递归的深度优先遍历,和广度优先遍历 package fifth; import java.util.Random; public class Tool ...

  6. 线索二叉树和中序非递归遍历线索化后的二叉树

    //线索二叉树 #include<stdio.h> #include<malloc.h> #include<process.h> #define OVERFLOW ...

  7. 【转】更简单的非递归遍历二叉树的方法

    [转]更简单的非递归遍历二叉树的方法 解决二叉树的很多问题的方案都是基于对二叉树的遍历.遍历二叉树的前序,中序,后序三大方法算是计算机科班学生必写代码了.其递归遍历是人人都能信手拈来,可是在手生时写出 ...

  8. 更简单的非递归遍历二叉树

    解决二叉树的很多问题的方案都是基于对二叉树的遍历.遍历二叉树的前序,中序,后序三大方法算是计算机科班学生必写代码了.其递归遍历是人人都能信手拈来,可是在手生时写出非递归遍历恐非易事.正因为并非易事,所 ...

  9. 更简单的非递归遍历二叉树的方法

    解决二叉树的很多问题的方案都是基于对二叉树的遍历.遍历二叉树的前序,中序,后序三大方法算是计算机科班学生必写代码了.其递归遍历是人人都能信手拈来,可是在手生时写出非递归遍历恐非易事.正因为并非易事,所 ...

最新文章

  1. 任务05—学习 MARKDOWN 语言
  2. 全球与中国聚硫聚合物市场发展前景与投资可行性分析报告2021年版
  3. 不会但一定要了解的方面,python列表解析方式
  4. Qtum量子链研究院:Plasma扩容方案详解(上)
  5. pic pwm 占空比可调 源码_PIC16F914输出可调占空比PWM波形程序
  6. 算法高级(2)-多年以前的电脑算命是怎么回事?
  7. Servlet过滤器示例及分析----日志过滤器 以及对flush()理解
  8. 软件测试是什么,测试从一个点出发。
  9. php pdf添加水印图片,php pdf添加水印(中文水印,图片水印)
  10. Java Thread 多线程 操作线程
  11. [C语言]——打印素数(质数)
  12. c语言 abs 不好用,c语言中 abs 和 fabs 不同吗?
  13. MCE | “神药”二甲双胍后,糖尿病药物研究谁将是下一个顶流?
  14. ZOJ1005 Jugs
  15. 共线性诊断 matlab,求共线性诊断结果的含义
  16. 图说三极管的三个工作状态
  17. opencv学习记录——(5)图像像素的操作
  18. 深度学习分类分到同一个类
  19. 查看、清空Linux日志【系统日志、软件运行日志】
  20. 所在地区级别_在人所在的地方

热门文章

  1. 基于proteus的功率_学习电路仿真:基于proteus电路仿真软件的步进电机仿真
  2. Android MTK Camera驱动代码分析
  3. 使用vimdiff做git的diff与merge工具
  4. 安卓购物商城源码(服务端+客户端)
  5. PCIE:如何获取PCIE学习资料文档
  6. 数据字典的设计--1.首页功能实现
  7. pic16F877A音乐盒c语言,基于PIC16F877A单片机的混沌信号发生器的设计
  8. python考证书-Python全国二级等级考试(2019)
  9. OpenCV入门 图像的边缘填充与融合
  10. 【操作系统】“哲学家进餐”问题