二叉树中序非递归遍历算法实现

大家好,我是逝去的粒子,从今天起,我将尝试着数据结构从0开始学习分享,此篇文章作为试验,一方面可以为自己做笔记防止遗忘,另一方面希望可以帮助大家。不废话,正式开始。

1.第一步,我们需要先序递归创建二叉树,栈,以及栈的基础方法,因为上述这些不是今天的重点且网上有很多讲解,我就不重复造轮子了,代码如下:

#include "stdio.h"
#include "stdlib.h"
#define MaxSize 50
typedef int ElemType;//树的定义
typedef struct BiTNode{int data;struct BiTNode *lchild,*rchild;
}BiTNode,*BiTree;//栈的定义
typedef struct{BiTree data[MaxSize];int top;
}SqStack;//初始化
void InitStack(SqStack &s){s.top=-1;
}//判断栈空
bool StackEmpty(SqStack &s){if(s.top==-1)return true;elsereturn false;
}   //进栈
bool Push(SqStack &s,BiTree x){if(s.top==MaxSize-1){return false;}s.data[++s.top]=x;return true;
}//出栈
BiTree Pop(SqStack &s,BiTree x){if(s.top==-1){return false;}x=s.data[s.top--];return x;
}//读取栈顶元素
bool GetTop(SqStack &s){BiTree x;if(s.top==-1){return false;}x=s.data[s.top];printf("%c",x->data);return true;
}
//创建二叉树,递归创建,默认先序输入
void CreateBiTree(BiTree &T){char c;scanf("%c",&c);if(c=='#'){T=NULL;}else{T=(BiTree)malloc(sizeof(BiTNode));T->data=c;CreateBiTree(T->lchild);CreateBiTree(T->rchild);}
}

2.第二步:假设我们先序遍历输入:12#46###3#5##,(#表示空节点),如下创建了一个这样的二叉树:

3.第三步:递归先序遍历,简单来说就是始终坚持先左后中再右,代码如下:

//中序遍历--递归
void InOrder(BiTree T){if(T!=NULL){InOrder(T->lchild);printf("%c",T->data);InOrder(T->rchild);}
}
简单来说就是将树T的指针传过来,依次遍历,有的人传的是指针的地址,效果都一样

--------------------------------接下来就是今天的重点了:非递归中序-------------------------

4.第4步非递归中序遍历算法思想-->借助栈,先有一个工作指针p,让其从头节点依次扫描左节点,并将扫描到的节点依次进栈,如果扫描的左节点为空了时,从栈中弹出一个节点,此时显然弹出的这个节点及其他的左子树都已经被访问过了,我们再使用p继续访问此节点的右节点,将其进栈,然后继续右孩子节点的所有左孩子,不停的迭代,直到所有节点全部访问过,并且栈为空。根据此思想,编写如下代码:

//中序遍历--非递归
void InOrder2(BiTree T){SqStack s;InitStack(s); //初始化栈BiTree p=T,a;        //遍历指针pwhile(p||!StackEmpty(s)){if(p){Push(s,p);p=p->lchild;}else{GetTop(s);    //在p出栈之前先查看a=Pop(s,p);     //出栈,a为接收出栈的p节点p=p->rchild;}}
}
1.首先初始化栈s,我用的是顺序栈,有能力的同学可以尝试着用链栈。
2.创建工作指是针p和a,其中p指向树T,也就是p指向节点1。
3.进入循环(p不为空或者栈s不为空时)执行循环体:做判断:如果工作指针p不为空,此时p指向的节点1进栈,p继续指向左子树指向了节点2,继续将2进栈,由于节点2没有左子树,所以进入else语句,出栈之前输出节点值,那么此时输出的就是2,并将节点2弹出栈,再寻找节点2的右节点,进入if语句,就这样不断迭代。

好了,现在我们看似代码还是比较ok的,因为我本身小白,没办法,此时,运行试试看。

果然没辜负我,又出错了,递归中序遍历能够正常实现,但非递归却只出现了一个数字2,再就没反应了,这是为什么。

5.第5步:调试阶段
为非递归这个函数添加一个断点,进行一步步调试,查看栈s以及p指针的变化。

直到有错误提示

此时我们发现了一个大问题,p指针的左右孩子都是为空,说明此时的p就是一个空指针,而且p的值为0x000000,有bug就解决,我发现,导致p错误的原因是当从栈中弹出一个节点时,我用的p指针已经不再是指向弹出那个节点的,而是指向了一个空节点,所以程序猜到else语句,对不对,那么原先写的p=p->lchild毫无疑问是错误的,此时,我想到用一个指针a来接收弹出的节点,然后将a赋给p,然后p代表当前弹出节点并继续访问其右节点。
如果有疑问的话,建议照着刚写的代码画着图实际演练一遍,或可以联系我。

//中序遍历--非递归
void InOrder2(BiTree T){SqStack s;InitStack(s); //初始化栈BiTree p=T,a;        //遍历指针pwhile(p||!StackEmpty(s)){if(p){Push(s,p);p=p->lchild;}else{GetTop(s);    //在p出栈之前先查看a=Pop(s,p);     //出栈,a为接收出栈的p节点p=a;p=p->rchild;}}
}


成功解决,当遇到bug时,要学会去调试代码,当然调试的前提是你必须要手动的会描述一个算法过程。今天的试验分享就到这,后面会不定期分享我会的数据结构,第一次写的不好请见谅。

数据结构之---非递归中序遍历二叉树相关推荐

  1. 非递归中序遍历二叉树总结(2种方法)

    算法 非递归中序遍历二叉树总结(2种方法) @author:Jingdai @date:2020.12.03 传送门 非递归先序遍历二叉树 非递归后序遍历二叉树 方法1 先序遍历是第一次遇到该节点遍历 ...

  2. 非递归前序遍历二叉树,非递归中序遍历二叉树,非递归后续遍历二叉树

    import java.util.Stack;public class Front {//非递归前序遍历public void front(TreeNode node) {Stack<TreeN ...

  3. 非递归中序遍历二叉树

    中序遍历二叉树(递归) void inOrder(BT* root) {if (root == NULL)return;inOrder(root->lchild);cout << & ...

  4. 非递归先序遍历二叉树总结(3种方法)

    算法 非递归先序遍历二叉树总结(3种方法) @author:Jingdai @date:2020.12.03 传送门 非递归中序遍历二叉树 非递归后序遍历二叉树 递归先序遍历二叉树非常的简单,但是面试 ...

  5. 非递归后序遍历二叉树总结(2种方法)

    算法 非递归后序遍历二叉树总结(2种方法) @author:Jingdai @date:2020.12.04 传送门 非递归先序遍历二叉树 非递归中序遍历二叉树 方法1 非递归用栈来辅助遍历,后序遍历 ...

  6. 无栈非递归中序遍历非线索化二叉树

    试设计一个非递归算法,按中根顺序遍历非线索二叉树,但不得用任何辅助. 在执行算法期间,允许改变LLINK和RLINK的值. 如何不用辅助栈非递归遍历二叉树呢? 这里给出了一个比较方便的算法,其基本思路 ...

  7. 二叉树非递归中序遍历

    二叉树的中序遍历 为什么把中序遍历放在最前面呢,因为在非递归遍历中,这个是最简单也是最容易理解的,所以放在第一个的位置. 中序遍历的递归算法很简单,但是想要非递归的实现,就要用到栈这个数据结构, 那么 ...

  8. 不用栈实现二叉树非递归中序遍历

    偶尔看到这样一个问题: 有个二叉树,每个节点除了左右指针外,还有一个指向父节点的指针. 要求不用递归,中序遍历这棵树.另要求空间复杂度是O(1). 空间复杂度为O(1),摆明就是不让用堆栈模拟递归,所 ...

  9. LeetCode:二叉树的非递归中序遍历

    第一次动手写二叉树的,有点小激动,64行的if花了点时间,上传leetcode一次点亮~~~ 1 /* inorder traversal binary tree */ 2 #include < ...

最新文章

  1. php广告轮播效果,使用swiper组件实现轮播广告效果
  2. MobPush精准把握用户的使用时间
  3. responsebody如何将数据转换成json的_干货分享:如何用Retrofit直接获得Json数据(字符串)...
  4. c语言cnn实现ocr字符,端到端的OCR:基于CNN的实现
  5. SAP Spartacus cxOutlet 里的 templatesRefs 的填充逻辑
  6. if sql语句_SQL IF语句介绍和概述
  7. 数据湖产业生态联盟会员权益
  8. linux下仿真流体计算软件,【流体】| 10个目前流行的CFD仿真软件,你了解几个?...
  9. 线性规划问题的模型建立与求解
  10. 无法ping通别的计算机名,解决主机无法ping通问题
  11. php和mysql web开发 目录_PHP和MySQL Web开发(原书第5版)简介,目录书摘
  12. 5.Linux系统中解压缩详解
  13. 动态代理实例——增强Waiter接口
  14. Vulnhub靶机系列:SecTalks: BNE0x03 - Simple
  15. tekton入门 - piplinerun
  16. 如何用Python投机倒把几天“暴富”
  17. 【西安电子科技大学】考研初试复试资料分享
  18. 成功改造企业文化的八项原则
  19. [数值计算-5]:一元二次非线性方程求解 - 解析法直接求解
  20. mediapipe之人脸特征点468检测

热门文章

  1. 爱奇艺适配鸿蒙,鸿蒙天尊_爱奇艺鸿蒙天尊官网
  2. jQuery DOM操作与简单事件
  3. [Linux] Centos7 挂载本地ISO镜像并配置yum源
  4. hbase行健设计原则
  5. EXCEL将一栏数据进行分隔处理
  6. linux关闭nvidia独显的方法
  7. XLua框架搭建——类型导出与黑名单
  8. 【硬件控制】1. Pico介绍
  9. 如何恢复删除的照片和视频?可以试试看
  10. redhat8版防火墙管理工具( iptables/firewalld)