【问题描述】
编写程序,实现二叉树的三种非递归遍历算法:先序非递归,中序非递归,后序非递归。
【输入形式】
输入建树序列。
【输出形式】
输出三种遍历序列。
【样例输入】
A
B
C
#
#
#
#
【样例输出】
ABC
CBA
CBA
要求:程序由接口文件(.h)和程序文件(.c)组成。接口文件包括:栈的结构、基本操作定义,二叉树的结构,二叉树的创建。程序文件包括三种非递归遍历定义及主函数。
我们需要在Code::Blocks中创建一个项目,里面的程序文件(.c)用来存放三种非递归遍历的定义及主函数。建立方式如下:
file->New->project->Console application
点击Next,(.c)文件创建完成。
接下来新建一个(.h)文件用来存放:栈的结构、基本操作定义,二叉树的结构,二叉树的创建。
File->New->Class->输入名称,点击creat->是->ok
输入名称,点击create
项目创建完成。
非递归算法中借助栈来完成整个遍历过程。步骤如下:
(1)当前指针指向根结点。
(2)若结点不为空,访问该结点。
(3)若结点右孩子不为空,则右孩子入栈。
(4)当前指针指向结点左孩子重复步骤(2)- 步骤(3),直到左孩子为空。
(5)依次退栈,当前指针指向出栈结点。
(6)若栈非空或当前指针非空,继续步骤(2),直到结束。
由此可写出先序遍历的非递归算法:
void PreOrder_n(BiTree p)
{
BiTree stack[MAX],q;
int top=0,i;
for(i=0;i<MAX;i++)stack[i]=NULL;//初始化栈
q=p;
while(q!=NULL)
{
printf("%c",q->data);//访问当前结点
if(q->rchild!=NULL)stack[top++]=q->rchild;//当前结点右孩子进栈
if(q->lchild!=NULL)q=q->lchild;//左子树不为空,进入左子树
else if(top>0)q=stack[--top];//左子树为空,栈不空,则出栈
else q=NULL;
}
}
(.h)文件中栈的结构、基本操作定义,二叉树的结构,二叉树的创建。代码如下:
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#define MAX 20
#define ERROR 0
#define OK 1
#define STACK_INT_SIZE 10
#define STACKINCREMENT 5
//二叉链表结点定义
typedef struct BTNode
{
char data;
struct BTNode *lchild;
struct BTNode *rchild;
}*BiTree;
void createBiTree(BiTree *t)
{
//此处补充代码,完成以先序遍历方式建立二叉树
char s;
BiTree q;
s=getchar();
getchar();
if(s=='#')
{
*t=NULL;
return;
}
q=(BiTree)malloc(sizeof(struct BTNode));
q->data=s;
*t=q;
createBiTree(&q->lchild);
createBiTree(&q->rchild);
}
typedef BiTree ElemType;
typedef struct
{
ElemType *base;
ElemType *top;
int stacksize;
} SqStack;
int initStack(SqStack *s);
int emptyStack(SqStack *s);
int pushStack(SqStack *s, ElemType e);
int popStack(SqStack *s,ElemType *e);
//初始化栈
int initStack(SqStack *s)
{
s->base=(ElemType *)malloc(STACK_INT_SIZE*sizeof(ElemType));
if(!s->base)return ERROR;
s->top=s->base;
s->stacksize=STACK_INT_SIZE;
return OK;
}
//判断栈空
int emptyStack(SqStack *s)
{
if(s->top==s->base)return OK;
else return ERROR;
}
//入栈
int pushStack(SqStack *s, ElemType e)
{
if(s->top-s->base>=s->stacksize)
{
s->base=(ElemType *)realloc(s->base,(s->stacksize+STACKINCREMENT)*sizeof(ElemType));
if(!s->base)return ERROR;
s->top=s->base+s->stacksize;
s->stacksize+=STACKINCREMENT;
}
*s->top++=e;
return OK;
}
//出栈
int popStack(SqStack *s,ElemType *e)
{
if(s->top==s->base)return ERROR;
--s->top;
*e=*s->top;
return OK;
}
(.c)文件中三种递归遍历及主函数的代码如下:
#include "ec1.z.h"/*这里要用你自己创建的(.h)文件的名称*/
void PreOrder_n(BiTree p)
{
BiTree stack[MAX],q;
int top=0,i;
for(i=0;i<MAX;i++)stack[i]=NULL;//初始化栈
q=p;
while(q!=NULL)
{
printf("%c",q->data);//访问当前结点
if(q->rchild!=NULL)stack[top++]=q->rchild;//当前结点右孩子进栈
if(q->lchild!=NULL)q=q->lchild;//左子树不为空,进入左子树
else if(top>0)q=stack[--top];//左子树为空,栈不空,则出栈
else q=NULL;
}
}
void InOrder_n(BiTree p)
{
BiTree stack[MAX],q;
int top=0,i;
for(i=0;i<MAX;i++)stack[i]=NULL;//初始化栈
q=p;
while(q!=NULL||top>0)
{
if(q!=NULL)
{
stack[top++]=q;
q=q->lchild;
}
else
{
q=stack[--top];
printf("%c",q->data);
q=q->rchild;
}
}
}
void PostOrder_n(BiTree p)
{
BiTree stack[MAX],q;
int top=0,i,flag[MAX];
for(i=0;i<MAX;i++)stack[i]=NULL;
for(i=0;i<MAX;i++)flag[i]=0;
q=p;
i=0;
while(q!=NULL||top>0)
{
if(q)
{
stack[top++]=q;
flag[i++]=0;
q=q->lchild;
}
else
{
while(top>0)
{
if(flag[i-1]==0)
{
q=stack[top-1]->rchild;
flag[i-1]=1;
break;
}
else
{
q=stack[--top];
i--;
printf("%c",q->data);
}
}
}
if(top==0)break;
}
}
int main()
{
//此处补充代码,按要求输出二叉树的叶子结点数和深度
BiTree p;
createBiTree(&p);
PreOrder_n(p);
printf("\n");
InOrder_n(p);
printf("\n");
PostOrder_n(p);
return 0;
}
运行结果如下: