C语言实现二叉树的非递归遍历:

代码解释:

非递归前序遍历:1> 首先建立一个二维指针,用来存储每个结点的地址,定义栈顶指针top,初始值为-1,并将根结点存入栈中,top++;2> 进入while循环,栈顶指针不为-1,则进入while循环,输出当前栈顶元素p的数据域,代表前序遍历的第一个结点为根结点;3> 如果当前的p结点拥有右子树,将这个右子树结点存入栈中,没有则不存;因为栈的特点是先进后出,所以先存右子树,在存左子树;4> 如果当前的p结点拥有左子树,将这个左子树结点存入栈中,没有则不存;5> 如果这个结点为叶子结点,那么直接将这个结点输出,不需要存结点;6> 再判断top是否为-1,之后重复执行2,3,4步骤;非递归中序遍历:1> 与非递归前序遍历相同,同样需要一个二维指针的栈,栈顶元素初始化为-1;2> 首先判断if的判断条件,这个二叉树不为空;3> 在进入if条件语句中的while循环,这个循环是将与根结点相连的所有左子树全部存入栈中;4> 退出循环后,在判断第二个while循环的条件,栈不为空,则进入while循环;5> 首先输出距离与根结点相连最远的左子树;6> 如果这个结点拥有右子树,先将这个右子树结点存入栈中;7> 在判断这个结点是否拥有左子树,有的话,将与这个结点相连的所有左子树存入栈中,没有就不执行while循环,并且结束判断结点是否拥有右子树的循环;7> 在判断top是否为-1,成立进入循环,重复上述步骤即可;存储总结:就是一直将与跟结点的所有左子树存入栈中,判断左后一个结点是否拥有右子树,有的话就把与这个结点相连的所有左子树存入栈中;非递归后序遍历:1> 同样建立一个二维指针的栈,用来存储每个结点的地址;2> 进入do-while循环,首先,将与根结点相连的所有左子树都存入栈中;3> 将BitTree类型的指针p赋空,判断while循环是否成立;4> 如果这个最后一个结点的右子树==p,则输出当前结点的数据域,栈顶指针--;5> 并将这个结点赋给指针p表示这个结点已经访问过,并且已经输出;6> 如果当前结点的右子树!=p,则接着访问这个结点的右子树,并且结束while循环,判断do-while循环的判断条件;7> 重复上述过程,知道不满足do-while循环的判断条件;存储总结:先将与根结点相连的所有左子树全部存入栈中,在判断左后一个结点是否有右子树,如果有则访问这个结点,没有的话就输出当前结点,当do-while循环中的两个while循环完成后,在判断do-while循环的条件,之后重复上述过程,直到不满足do-while循环条件;

代码实现:

#include <stdio.h>
#include <stdlib.h>
#define N 20//二叉树结点的结构体表示形式
typedef struct tree
{char ch;struct tree *lchild;struct tree *rchild;
}BitTree;//创建二叉树,利用递归的方法
//按前序次序输入。 如 A # #(#表示空树)
BitTree *CreateTree()
{BitTree *bt;char str; scanf("%c",&str);if (str=='#')return NULL;else{bt=(BitTree *)malloc(sizeof(BitTree));bt->ch=str;bt->lchild=CreateTree();bt->rchild=CreateTree();return bt;}
}//前序遍历的非递归实现
/*思想:利用栈来实现;根结点进栈,之后栈非空,弹出,接着根节点的右结点进栈,之后,左节点进栈;接着,弹出栈顶元素(输出),此结点的右结点进栈,之后左节点进栈,弹出栈顶元素(输出)...一直这样下去,直到栈为空。*/
void PreOrder(BitTree *bt)
{BitTree **s;BitTree *p;int top=-1;//创建栈;s=(BitTree **)malloc((N+1)*sizeof(BitTree *));//初始化栈;s[++top]=bt;//非递归前序遍历;while(top!=-1){p=s[top--];printf("%c ",p->ch);    //栈的特点,先进后出;if(p->rchild)s[++top]=p->rchild;if(p->lchild)s[++top]=p->lchild;}free(s);
}//中序遍历,非递归实现
/*思想:利用栈。从根节点开始循环,只要有左子节点则进栈,直到左子节点为空。接着弹出栈顶输出,判断该结点是否有右子节点,若有则进栈,若没有继续弹栈。有右子节点的情况,判断该节点是否有左子节点,有则进栈,直到左子节点为空;若该右子节点没有左子节点,则弹栈;判断弹出的节点,是否有右子节点,若有则进栈,没有继续弹栈;接着又要判断刚进栈的这个节点,是否有左子节点,有则进栈,没有则继续弹栈。重复下去....栈空,是判定条件。*/
void InOrder(BitTree *bt)
{BitTree **s;BitTree *p,*q;int top=-1;//创建栈;s=(BitTree **)malloc((N+1)*sizeof(BitTree *));//非递归中序遍历;if(bt){while(bt)   //一直遍历左子树直到该结点的左孩子空为止;{s[++top]=bt;   //将所有左孩子存入栈中;bt=bt->lchild;     //指向下一个左子树;}while(top!=-1)  //栈空时结束循环;{p=s[top--];//刚开始将最p指向左下角的左孩子,并且移向该结点的父结点;printf("%c ",p->ch);  //输出左下角的结点;while(p->rchild)  //遍历移动后结点有没有右结点;{s[++top]=p->rchild;   //将这个结点的右子树入栈;q=p->rchild;          //这个右子树结点赋给q;while(q->lchild)      //判断结点q有没有左子树;{s[++top]=q->lchild;  //有左子树,将与这个结点相连的所有左子树都入栈;q=q->lchild;}break;   //结束当前循环,回到第二个while循环继续刚才的步骤;}}}
}//后序遍历,非递归实现
/*算法思想:利用栈来实现。从根结点开始,只要左子节点非空,则进栈,直到左子节点为空为止。取出栈顶元素(只是取,并非弹栈),判断:1:取出的栈顶元素是否有右子节点,或者右子节点是否被访问过,若满足条件(无右子节点,或者右子节点被访问过),则输出该结点,同时弹栈,并且记录下该访问的节点。2:取出的栈顶元素,若有右子节点,且未被访问过,则指针继续移动到右子节点,重复一开始是否又左子节点的判断。
*/
void PostOrder(BitTree *bt)
{   BitTree **s;BitTree *p;int top=-1;//创建栈;s=(BitTree **)malloc((N+1)*sizeof(BitTree *));//非递归后序遍历;do{while(bt)     //一直遍历左子树直到该左子树的左孩子空为止;{s[++top]=bt;     //将所有左孩子存入栈中;bt=bt->lchild;   //指向下一个左子树;}p=NULL;while(top!=-1){bt=s[top];if(bt->rchild==p)  //p:表示为null,或者右子节点被访问过了;{printf("%c ",bt->ch);   //输出结点数据域;top--;           //输出以后,top--;p=bt;  //p记录下刚刚访问的节点;}else{bt=bt->rchild;   //访问右子树结点;break;}}}while(top!=-1);
}int main()
{printf("请以顺序输入二叉树(#表示该结点的子结点为空):\n");BitTree *btr=CreateTree();printf("前序遍历非递归实现:\n");PreOrder(btr);printf("\n");printf("中序遍历非递归实现:\n");InOrder(btr);printf("\n");printf("后序遍历非递归实现:\n");PostOrder(btr);printf("\n");return 0;
}

实现截图:

C语言实现二叉树的非递归遍历相关推荐

  1. C语言实现 二叉树 的非递归遍历(详细图解)(基于栈的顺序存储)

    分析主要分析二叉树的非递归遍历,基于栈顺序存储二叉树的节点. 1 实现思路(具体的分析过程会在以下函数实现部分分析,中序遍历如下) 将树的所有节点标志位置为假(0),并将根节点压入栈中 进入循环,只要 ...

  2. c语言以顺序结构存储的二叉树的非递归遍历,C语言二叉树的非递归遍历实例分析...

    本文以实例形式讲述了C语言实现二叉树的非递归遍历方法.是数据结构与算法设计中常用的技巧.分享给大家供大家参考.具体方法如下: 先序遍历: void preOrder(Node *p) //非递归 { ...

  3. 二叉树的非递归遍历(C语言实现)

    上一篇讨论了二叉树的的递归遍历,这一次讨论二叉树的三种非递归遍历 二叉树的非递归遍历采用栈实现,首先给出二叉树和栈的定义 #define STACK_INIT_SIZE 100 #define STA ...

  4. 二叉树的非递归遍历(统一的模板)

    二叉树的非递归遍历 前言 树的存储结构 先序遍历 先序的递归遍历 先序的非递归遍历 中序遍历 中序的递归遍历 中序遍历的非递归算法 后序遍历 后序的递归遍历 后序的非递归遍历 层次遍历 层次遍历获得每 ...

  5. 刷题:二叉树的非递归遍历方式

    二叉树的非递归的遍历方式 上篇博客记录了二叉树的递归遍历方式以及根据二叉树的遍历结果还原二叉树的内容. 本篇博客记录二叉树的非递归的遍历方式. 二叉树的非递归遍历需要借助栈来实现,而且三种遍历的方式的 ...

  6. 二叉树的非递归遍历(c/c++)

    由于递归算法相对于非递归算法来说效率通常都会更低,递归算法会有更多的资源需要压栈和出栈操作(不仅仅是参数,还有函数地址等)由于编译器对附加的一些栈保护机制会导致递归执行的更加低效,使用循环代替递归算法 ...

  7. 数据结构-二叉树的非递归遍历

    前面的章节我们实现了二叉树最基本的遍历方式:递归遍历,代码是如此的简洁:辣么我们为什么还要去学习二叉树的非递归遍历方式呢?众所周知,递归优点是将可以将复杂的问题简单化即大问题拆分成一个个小问题,那么它 ...

  8. 树:二叉树的非递归遍历算法

    二叉树的递归遍历 二叉树的递归遍历算法,写法很简单,比如说前序遍历树,如下: //前序遍历 void PreOrderTraverse(BiTree tree) {if (NULL != tree){ ...

  9. 6-9 二叉树的非递归遍历 (20 分)

    ** 6-9 二叉树的非递归遍历 (20 分) ** 本题要求用非递归的方法实现对给定二叉树的 3 种遍历. 函数接口定义: void InorderTraversal( BinTree BT ); ...

最新文章

  1. 如何快速优化机器学习的模型参数
  2. Face Recognition for the Happy House-v3
  3. 大家都纷纷指出了 wp7 的优点 …
  4. python话雷达图-python使用matplotlib绘制雷达图
  5. VCSA中配置时间和时区,实测至6.5适用
  6. Jenkisn之JDK-MVN-ANT-GRADLE
  7. Mysql数据库开发的36条原则
  8. *【CodeForces - 280C】Game on Tree(期望模型,期望的线性性)
  9. 单播 广播 组播_组播概念3
  10. 对 React 组件进行单元测试(unit testing)
  11. cl.exe is unable to create an executable file. C compiler test failed.
  12. win7 64位 纯净版旗舰版202104
  13. Google翻译接口调用
  14. 环境数据采集系统——中期总结
  15. 生产环境lepus部署 监控MySQL
  16. 项目过程管理(十八)集体加班制度
  17. jmeter第21讲 阿里云下载安装JDK并配置环境变量
  18. C++基础(1)- 声明(前向声明 Forward Declaration)与定义
  19. 球差产生的原因、定量分析和校正方法(zemax)
  20. 尚硅谷在线教育六:尚硅谷在线教育课程分类管理开发

热门文章

  1. 2、数据库系统是什么?它由哪几部分组成?
  2. 四种发生器的使用方法——FlexSim
  3. 书法作品中印章的使用
  4. 做硬件好还是软件好,千万别选错了路!
  5. 我的世界java版合成表_《我的世界》基础攻略 JAVA版合成系统详解
  6. Nacos 学习笔记2 - 搭建 Nacos 集群
  7. wyh的商机(tarjan离线求lca)
  8. Java中一种计算Hash值的算法——SHA-256
  9. Sentinel的规则
  10. 服务器raid模式修改成ide,SkyIAR 2.57 IDE_AHCI_RAID模式修改方案