任务描述
相关知识
栈的基本操作函数接口
先序遍历的非递归算法
中序遍历的非递归算法
编程要求
测试说明
任务描述
本关任务:以二叉链表作存储结构存储二叉树,利用先序递归遍历创建二叉树,并进行二叉树中序非递归遍历。
相关知识
二叉树是一种非常重要的数据结构,很多其他数据机构都是基于二叉树的基础演变过来的。
二叉树有前、中、后三种遍历方式,因为树的本身就是用递归定义的,因此采用递归的方法实现三种遍历,不仅代码简洁且容易理解,但其开销也比较大。
若采用非递归方法实现三种遍历,则要用栈来模拟实现(递归也是用栈实现的)。
栈的基本操作函数接口
本关卡提供顺序栈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 **********/
}