在此之前,我们已经学习了中序遍历二叉树的递归算法,相信大家已经将其牢牢掌握了.

除了使用递归思想作为求解问题的钥匙,还可以借助栈来以非递归方式实现该问题的求解.

首先,我们要讨论存储二叉树结点信息的栈的形态:是只存储二叉树结点的指针,还是要完整存储二叉树结点的信息(LChild指针+数据域data+RChild指针). 在这里先和大家说明,经过程序执行验证,(※)必须将二叉树结点的信息完整入栈,而不能像层次遍历时那样只把结点指针存入队列.

接下来我们来看一下二叉树结点栈的定义形式.

struct Stack//栈的定义
{int base;//栈底指针int top;//栈顶指针BiTreeNode BTNS[MAXSIZE];//二叉树结点数组int stackSize;//栈可用的最大容量
};

[注]:BTNS[]数组为二叉树结点数组,该数组即为顺序栈的空间.

接着,我们需要初始化二叉树结点栈.

void InitStack(Stack* &S)//初始化栈
{S=(Stack*)malloc(sizeof(Stack));S->top=S->base=0;S->stackSize=MAXSIZE;
}

为了算法的严谨,我们还需要在栈空和栈满时做出反应,以避免越界访问数组的问题发生.

bool StackEmpty(Stack* &S)//判断栈是否为空
{if(S->base==S->top){return true;}else{return false;}
}
bool StackFull(Stack* &S)//判断栈是否已满
{if(S->top - S->base == S->stackSize){//栈已满return true;}else{//栈不满return false;}
}

最后,还需要二叉树结点进出栈的操作.

void Push(Stack* &S, BiTreeNode* &T)//元素入栈
{if(StackFull(S)==true){//如果栈已满, 则直接返回return ;}//把结点信息复制到栈中S->BTNS[S->top].data=T->data;S->BTNS[S->top].LChild=T->LChild;S->BTNS[S->top].RChild=T->RChild;S->top++;//元素入栈 -> 将结点信息复制到栈的某个位置中(※)//一开始我选择将结点指针入栈, 但如此做会导致程序报错//一直找不出问题, 后来才发现这样做是错误的
}
BiTreeNode* Pop(Stack* &S)//元素出栈
{if(StackEmpty(S)==true){//栈已空return NULL;}S->top--;//栈顶"指针"下移return &(S->BTNS[S->top]);
}

[注]:如果有朋友对上面栈的操作理解不透彻,这里先将栈看作一个增广的数据类型即可:即直接使用其操作函数,不必在意其实现细节. 我会在六月中旬到七月上旬间和大家分享有关线性结构的相关操作算法.

有了辅助栈的帮忙,我们距离实现算法又近了一步. 接下来我们需要分析中序遍历的非递归过程.

我们在中序遍历一棵二叉树时,遵循的规则为"左根右":据此遍历规则,可以得到下面的思维过程:

①p指向树根结点;

②如果p非空,那么跳转至③;如果p为空,那么跳转至④;

③p=p->LChild(p指向原来指向结点的左孩子结点),跳转至②;

④栈顶元素出栈,并使指向出栈元素,p=q->RChild(p指向出栈元素的右孩子结点),跳转至②;

依据上面的思维过程,我们不难看出,该算法无法结束:我们还必须考虑算法的结束条件. 当p=NULL时,如果栈也空了,那么说明所有的结点都被访问过了,此时算法结束.

据此分析,将上面的思维过程改写为下面的形式:

①p指向树根结点;

②如果p非空,那么跳转至③;如果p为空且辅助栈不空,那么跳转至④;如果p为空且辅助栈也为空,那么跳转至⑤;

③p=p->LChild(p指向原来指向结点的左孩子结点),跳转至②;

④栈顶元素出栈,并使指向出栈元素,p=q->RChild(p指向出栈元素的右孩子结点),跳转至②;

⑤结束.

由此思维过程,得到下面的算法实现代码.

void InOrderTraverse(Stack* &S, BiTreeNode* &T)//中序遍历二叉树的非递归算法(※)
{InitStack(S);//初始化栈BiTreeNode* p=T;BiTreeNode* q;while(p||!StackEmpty(S)){//当p=NULL且栈空时, 循环结束if(p){//根结点入栈Push(S,p);//继续往左下方走p=p->LChild;}else{//左下方没路了, 访问栈顶元素,并将其出栈q=Pop(S);//出栈元素指针保存在q中putchar(q->data);cout<<"  ";//之后再往出栈元素的右下方走p=q->RChild;}}
}

大家应着重掌握这里的中序遍历非递归算法,这对培养算法思维有着极大的帮助.

还有一点值得说明,那就是当你把栈和队列看作一种增广的数据类型(使用栈和队列的相关操作时,忽略其内部实现细节)时,那么你的数据结构能力已经成功地从"菜鸟"级别迈入"初学者"级别了.

[完整源程序代码]:

#include<iostream>
#include<stdlib.h>
#include<stdio.h>
#define MAXSIZE 20
using namespace std;
struct BiTreeNode//二叉树结点定义
{BiTreeNode* LChild;//左孩子指针域int data;BiTreeNode* RChild;//右孩子指针域
};
struct Stack//栈的定义
{int base;//栈底指针int top;//栈顶指针BiTreeNode BTNS[MAXSIZE];//二叉树结点数组int stackSize;//栈可用的最大容量
};
void InitStack(Stack* &S)//初始化栈
{S=(Stack*)malloc(sizeof(Stack));S->top=S->base=0;S->stackSize=MAXSIZE;
}
bool StackEmpty(Stack* &S)//判断栈是否为空
{if(S->base==S->top){return true;}else{return false;}
}
bool StackFull(Stack* &S)//判断栈是否已满
{if(S->top - S->base == S->stackSize){//栈已满return true;}else{//栈不满return false;}
}
void Push(Stack* &S, BiTreeNode* &T)//元素入栈
{if(StackFull(S)==true){//如果栈已满, 则直接返回return ;}//把结点信息复制到栈中S->BTNS[S->top].data=T->data;S->BTNS[S->top].LChild=T->LChild;S->BTNS[S->top].RChild=T->RChild;S->top++;//元素入栈 -> 将结点信息复制到栈的某个位置中(※)//一开始我选择将结点指针入栈, 但如此做会导致程序报错//一直找不出问题, 后来才发现这样做是错误的
}
BiTreeNode* Pop(Stack* &S)//元素出栈
{if(StackEmpty(S)==true){//栈已空return NULL;}S->top--;//栈顶"指针"下移return &(S->BTNS[S->top]);
}
//
void CreateBiTree(BiTreeNode* &T)//以先序序列创建二叉树
{char ch;cin>>ch;if(ch!='#'){T=(BiTreeNode*)malloc(sizeof(BiTreeNode));T->data=ch;CreateBiTree(T->LChild);CreateBiTree(T->RChild);}else{T=NULL;}
}
void InOrderTraverse(Stack* &S, BiTreeNode* &T)//中序遍历二叉树的非递归算法(※)
{InitStack(S);//初始化栈BiTreeNode* p=T;BiTreeNode* q;while(p||!StackEmpty(S)){if(p){Push(S,p);p=p->LChild;}else{q=Pop(S);//出栈元素指针保存在q中putchar(q->data);cout<<"  ";p=q->RChild;}}
}
int main()
{Stack* S;BiTreeNode* T;CreateBiTree(T);InOrderTraverse(S,T);return 0;
}

(※)中序遍历二叉树的非递归算法相关推荐

  1. 数据结构二叉树中序遍历递归和非递归算法

    2022.11.19 二叉树中序遍历递归和非递归算法 任务描述 相关知识 编程要求 测试说明 C/C++代码 任务描述 本关任务:给定一棵二叉树,使用递归和非递归的方法实现二叉树的中序遍历结果. 相关 ...

  2. 中序遍历二叉树的非递归实现(利用栈)

    中序遍历二叉树的非递归实现 之前的博客写了递归的实现,说白了也就是不断自己调用自身,保持左根右的顺序.只需写出整体逻辑结构,程序会自己递归复杂的过程,大体即为: void inTraverseByRe ...

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

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

  4. 二叉树的中序遍历-递归和非递归算法

    创建二叉树就不说了,这里直接: 中序递归遍历算法 void InOrder(BiTree T){if(T){InOrder(T->lchild);cout<<T->data&l ...

  5. 树与二叉树——后序遍历二叉树的非递归算法

    算法思想:后序非递归遍历二叉树是先访问左子树,再访问右子树,最后访问根节点. ①若根节点有左孩子,则左孩子以此入栈,直到左孩子为空,然后读取栈顶元素,若其右孩子不为空且未被访问过,则对右子树执行①.否 ...

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

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

  7. C语言 中序遍历二叉树--非递归算法

    完整代码如下: #include <stdio.h> #include <stdlib.h> #include <string.h>typedef struct B ...

  8. 中序建立二叉树,非递归前序遍历二叉树

    内容: 编写程序,实现下述功能,并上机调试通过. 按中序顺序建立一棵二叉树: 用非递归方式遍历二叉树(先序),输出遍历序列. 步骤: 算法分析 采用二叉链表做存储结构,建立二叉树,借助于栈结构来实现二 ...

  9. 二叉树——中序遍历(递归/非递归)

    中序遍历,即遍历顺序为:左节点.根节点.右节点. 二叉树节点: public class Node {public Node left;public Node right;public int val ...

最新文章

  1. mysql定义条件和处理_MySQL定义条件和处理程序
  2. Flask上下文管理源码分析
  3. angularjs php登录验证,AngularJs表单验证的方法
  4. 你知道怎么在生产环境下部署tomcat吗?,灵魂拷问
  5. python解释器的安装步骤-Python本地及虚拟解释器配置过程解析
  6. 服务器和云服务器的安全性哪个更好?—Vecloud
  7. java 鉴权_我爱java系列之---【JWT实现微服务鉴权(一)】
  8. 电脑刚开机显示正在锁定计算机在怎么回事,电脑开机一直停留在诊断自动修复界面怎么回事...
  9. 【ICCV2019】点云相关论文解析
  10. [转载]Shell正则表达式
  11. 递归调用、高阶函数、装饰器
  12. libvpx在windows下的编译
  13. JAVA结合AE(Adobe After Effects),通过解析AE源文件AEPX,替换素材,渲染合成,转码等操作
  14. cocos 躲避球游戏(3) --群组碰撞
  15. 基于 requests 的全能扫描王爬虫实践
  16. js实现图片裁剪功能
  17. STM32蜂鸣器实例详解
  18. vue之原生上传图片并压缩图片大小(1)
  19. 磨金石教育分享:43款字体设计工具大集合,超赞!
  20. 考研html模板素材,2020考研英语作文模板素材:品质类模板

热门文章

  1. WinMain:应用程序入口点【WinMain: The Application Entry Point】
  2. 2022/1/23(每周总结)
  3. 阅读Logback文档笔记--Logback的Appender配置
  4. 泽塔云荣膺“中国高科技高成长50强”,成唯一上榜超融合企业
  5. linux的音频处理软ubuntu,Ubuntu18.04下的音频录制和编辑软件Ardour及QjackCtl(jackd gui)...
  6. MIFI与随身wifi、wifi共享软件,玩坏wifi的几种方法
  7. JAVA日志记录方法
  8. 推荐!非常好用的sql审核平台——Yearning
  9. 卸妆·回归:“超级医保局时代“的医院信息化转型
  10. 细数 GameFi 模型发展 ,未来仍可期?