数据结构实验43.docx
《数据结构实验43.docx》由会员分享,可在线阅读,更多相关《数据结构实验43.docx(12页珍藏版)》请在冰豆网上搜索。
数据结构实验43
实验4二叉树遍历算法的设计与实现
实验人:
学号:
时间:
一、实验目的
1.掌握二叉树的建立与存储
2.掌握二叉树的遍历方法
二、实验内容
编写程序实现根据用户输入二叉树的先序序列建立一棵二叉树,并实现对此二叉树的先序、中序、和后序遍历。
(算法6.4)
三、实验步骤:
1.接收用户输入的先序序列建立以二叉链表为存储结构的二叉树(算法6.4)。
2.对建立好的二叉树实现先序、中序、和后序遍历,将遍历后的序列输出(参考算法6.1,6.3)。
其中中序遍历包括递归和非递归算法实现,先序、后序遍历只要求递归算法实现即可。
四、算法说明
1.二叉树的二叉链表存储表示(结构体)
2.按先序次序输入二叉树中结点的值,#表示空树
3.访问二叉树中元素
4.递归先序遍历
5.递归中序遍历
6.递归后序遍历
7.主函数依次调用上述函数
五、测试结果
对以下二叉树进行验证
A
/\
BC
/\/\
DEFG
六、分析与探讨
1.用按先序遍历输入的方法输入的字符画出二叉树,看图依次按先序、中序、后序的方法写出遍历后的序列与测试结果对比可知正确。
2.我在本实验中都是按递归的方法实现遍历,用栈操作也实现了非递归的遍历。
七、附录:
源代码
#include
#include
//函数结果状态代码
#defineTRUE1
#defineFALSE0
#defineOK1
#defineERROR0
#defineINFEASIBLE-1
#defineOVERFLOW-2//因为在math.h中已定义OVERFLOW的值为3,故去掉此行
#defineSTACK_INIT_SIZE100//存储空间初始分配量
#defineSTACKINCREMENT10//存储空间分配增量
typedefintStatus;//Status是函数的类型,其值是函数结果状态代码,如OK等
typedefintBoolean;//Boolean是布尔类型,其值是TRUE或FALSE
//二叉树结点
typedefstructBiTNode{
//数据
chardata;
//左右孩子指针
structBiTNode*lchild,*rchild;
}BiTNode,*BiTree;
typedefstructSqStack
{
BiTree*base;//在栈构造之前和销毁之后,base的值为NULL
BiTree*top;//栈顶指针*/
intstacksize;//当前已分配的存储空间,以元素为单位
}SqStack;//顺序栈
//按先序序列创建二叉树
intCreateBiTree(BiTree&T){
chardata;
//按先序次序输入二叉树中结点的值(一个字符),‘#’表示空树
scanf("%c",&data);
if(data=='#'){
T=NULL;
}
else{
T=(BiTree)malloc(sizeof(BiTNode));
//生成根结点
T->data=data;
//构造左子树
CreateBiTree(T->lchild);
//构造右子树
CreateBiTree(T->rchild);
}
return0;
}
//输出
voidVisit(BiTreeT){
if(T->data!
='#'){
printf("%c",T->data);
}
}
//先序遍历
voidPreOrder(BiTreeT){
if(T!
=NULL){
//访问根节点
Visit(T);
//访问左子结点
PreOrder(T->lchild);
//访问右子结点
PreOrder(T->rchild);
}
}
//中序遍历
voidInOrder(BiTreeT){
if(T!
=NULL){
//访问左子结点
InOrder(T->lchild);
//访问根节点
Visit(T);
//访问右子结点
InOrder(T->rchild);
}
}
//后序遍历
voidPostOrder(BiTreeT){
if(T!
=NULL){
//访问左子结点
PostOrder(T->lchild);
//访问右子结点
PostOrder(T->rchild);
//访问根节点
Visit(T);
}
}
//栈的基本操作
StatusInitStack(SqStack&S)
{//构造一个空栈S
S.base=(BiTree*)malloc(STACK_INIT_SIZE*sizeof(BiTree));
if(!
S.base)
exit(-2);/*存储分配失败*/
S.top=S.base;
S.stacksize=STACK_INIT_SIZE;
returnOK;
}
StatusStackEmpty(SqStackS)
{/*若栈S为空栈,则返回TRUE,否则返回FALSE*/
if(S.top==S.base)
returnTRUE;
else
returnFALSE;
}
StatusGetTop(SqStackS,BiTree&e)
{/*若栈不空,则用e返回S的栈顶元素,并返回OK;否则返回ERROR*/
if(S.top>S.base)
{
e=*(S.top-1);
returnOK;
}
else
returnERROR;
}
StatusPush(SqStack&S,BiTreee)
{/*插入元素e为新的栈顶元素*/
if(S.top-S.base>=S.stacksize)/*栈满,追加存储空间*/
{
S.base=(BiTree*)realloc(S.base,(S.stacksize+STACKINCREMENT)*sizeof(BiTree));
if(!
S.base)
exit(-2);/*存储分配失败*/
S.top=S.base+S.stacksize;
S.stacksize+=STACKINCREMENT;
}
*S.top++=e;
returnOK;
}
StatusPop(SqStack&S,BiTree&e)
{/*若栈不空,则删除S的栈顶元素,用e返回其值,并返回OK;否则返回ERROR*/
if(S.top==S.base)
returnERROR;
e=*--S.top;
returnOK;
}
/*先序遍历(非递归)
思路:
访问T->data后,将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,再先序遍历T的右子树。
*/
voidPreOrder2(BiTreeT){
//p是遍历指针
BiTreep=T;
SqStackS;
InitStack(S);
//栈不空或者p不空时循环
while(p||!
StackEmpty(S)){
if(p!
=NULL){
//存入栈中
Push(S,p);
//访问根节点
printf("%c",p->data);
//遍历左子树
p=p->lchild;
}
else{
//退栈
Pop(S,p);
//访问右子树
p=p->rchild;
}
}//while
}
/*中序遍历(非递归)
思路:
T是要遍历树的根指针,中序遍历要求在遍历完左子树后,访问根,再遍历右子树。
先将T入栈,遍历左子树;遍历完左子树返回时,栈顶元素应为T,出栈,访问T->data,再中序遍历T的右子树。
*/
voidInOrder2(BiTreeT){
SqStackS;
//p是遍历指针
BiTreep=T;
InitStack(S);
//栈不空或者p不空时循环
while(p||!
StackEmpty(S)){
if(p!
=NULL){
//存入栈中
Push(S,p);
//遍历左子树
p=p->lchild;
}
else{
//退栈,访问根节点
Pop(S,p);
printf("%c",p->data);
//访问右子树
p=p->rchild;
}
}//while
}
/*
//后序遍历(非递归)
typedefstructBiTNodePost{
BiTreebiTree;
chartag;
}BiTNodePost,*BiTreePost;
voidPostOrder2(BiTreeT){
stackstack;
//p是遍历指针
BiTreep=T;
BiTreePostBT;
//栈不空或者p不空时循环
while(p!
=NULL||!
stack.empty()){
//遍历左子树
while(p!
=NULL){
BT=(BiTreePost)malloc(sizeof(BiTNodePost));
BT->biTree=p;
//访问过左子树
BT->tag='L';
stack.push(BT);
p=p->lchild;
}
//左右子树访问完毕访问根节点
while(!
stack.empty()&&(stack.top())->tag=='R'){
BT=stack.top();
//退栈
stack.pop();
printf("%c",BT->biTree->data);
}
//遍历右子树
if(!
stack.empty()){
BT=stack.top();
//访问过右子树
BT->tag='R';
p=BT->biTree;
p=p->rchild;
}
}//while
}
//层次遍历
voidLevelOrder(BiTreeT){
BiTreep=T;
//队列
queuequeue;
//根节点入队
queue.push(p);
//队列不空循环
while(!
queue.empty()){
//对头元素出队
p=queue.front();
//访问p指向的结点
printf("%c",p->data);
//退出队列
queue.pop();
//左子树不空,将左子树入队
if(p->lchild!
=NULL){
queue.push(p->lc