第6关:非递归实现二叉树的中序遍历

任务描述
相关知识
栈的基本操作函数接口
先序遍历的非递归算法
中序遍历的非递归算法
编程要求
测试说明
任务描述
本关任务:以二叉链表作存储结构存储二叉树,利用先序递归遍历创建二叉树,并进行二叉树中序非递归遍历。

相关知识
二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的。

二叉树有前、中、后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大。

若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的)。

栈的基本操作函数接口
本关卡提供顺序栈SeStack的相关操作和功能,顺序栈数据类型定义及相关操作函数接口定义如下,在进行非递归中序遍历二叉树的过程中,你可以根据需要调用以下操作。

typedef   struct
{          
    SElemType     *base;    //栈的基址即栈底指针          
    SElemType     *top;     //栈顶指针          
   int      stacksize;       //当前分配的空间 
}SqStack; 
void InitStack(SqStack &S);    // 构造一个空栈S
void DestroyStack(SqStack &S); // 销毁栈S,S不再存在
void ClearStack(SqStack &S);   // 把S置为空栈
int StackEmpty(SqStack S);     // 若栈S为空栈,则返回TRUE,否则返回FALSE
int StackLength(SqStack S);    // 返回S的元素个数,即栈的长度
int GetTop(SqStack S,SElemType &e);  // 若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR
void Push(SqStack &S,SElemType e);    // 插入元素e为新的栈顶元素
int Pop(SqStack &S,SElemType &e);     // 若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR
void StackTraverse(SqStack S,void(*visit)(SElemType)); // 从栈底到栈顶依次对栈中每个元素调用函数visit()
  
先序遍历的非递归算法
根据先序遍历的顺序,先访问根节点,再访问左子树,后访问右子树,而对于每个子树来说,又按照同样的访问顺序进行遍历,非递归的实现思路如下:

将非空根结点进栈
while (栈不为空)
{
    退栈,将栈顶元素赋给s;
    访问s的数据域
   if (s右子树不为空) 
    右子树入栈
    if (s左子树不为空) 
    左子树入栈
}
对应的先序遍历的非递归算法如下:

void ProOrderTraverse(BiTree T,void(*Visit)(TElemType))
{  // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
   // 先序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit
  SqStack s;//定义并初始化栈
  InitStack(s);
  BiTNode * p;
  if(T==NULL)
      return;
  Push(s,T);
  while(!StackEmpty(s))
  {
    Pop(s,p);
    Visit(p->data); 
    if(p->rchild)
        Push(s, p->rchild);
    if(p->lchild)
        Push(s, p->lchild);
  }
  DestroyStack(s);   
}  
中序遍历的非递归算法
中序遍历的非递归和前序遍历的非递归很相似,只是前序遍历是根-左-右,而中序遍历左-根-右,也就是说,中序遍历是:先遇到根节点不访问,而是直接压入栈,当左子树节点为空时,取出左子树节点,并访问左子树节点的右子树。

中序遍历的非递归算法思想:

如果当前结点有左子树,则该结点入栈;如果没有左子树,则访问该结点;
如果结点有右子树,则重复第1步;如果没有右子树,则回退,让此时的栈顶元素出栈,访问栈顶元素,并访问栈顶元素的右子树,重复第1步,第2步;
如果栈为空,则表示遍历结束。
注意:入栈结点本身没有被访问过,同时,其右子树也没有被访问过。

编程要求
根据提示,在右侧编辑器补充代码,实现下列函数:

InOrderTraverse(BiTree T,void(*Visit)(TElemType))//中序非递归遍历二叉树T,对每个结点调用函数Visit一次且仅一次
测试说明
平台会对你编写的代码进行测试:

测试输入:
ABD##FE###CG#H##I##

预期输出:
中序遍历为:D,B,E,F,A,G,H,C,I,

开始你的任务吧,祝你成功!

 
#include <stdio.h>
#include <stdlib.h>
#include "bitree.h"
#include "sqstack.h"


void InOrderTraverse2(BiTree T,void(*Visit)(TElemType));// 中序非递归遍历二叉树



int main()
{
	BiTree T;	
	CreateBiTree(T);
	printf("中序遍历:");
	InOrderTraverse2(T,visit);
	printf("\n");
  DestoryBiTree(T);	
	return 0;
}


void InOrderTraverse2(BiTree T,void(*Visit)(TElemType))
{  // 采用二叉链表存储结构,Visit是对数据元素操作的应用函数。
   // 中序遍历二叉树T的非递归算法,对每个数据元素调用函数Visit
  /********** Begin *********/
  SqStack s;
  InitStack(s);
  BiTNode* p=T;
  if(T==NULL)
  return;
  while(p||!StackEmpty(s))
  {
      if(p)
      {
          Push(s,p);
          p=p->lchild;
      }
      else{
          Pop(s,p);
          Visit(p->data);
          p=p->rchild;
      }
  }
  
  /********** End **********/
 }


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值