数据结构实验报告

更新时间:2023-09-02 02:43:01 阅读量: 教育文库 文档下载

说明:文章内容仅供预览,部分内容可能不全。下载后的文档,内容与下面显示的完全一致。下载之前请确认下面内容是否您想要的,是否完整无缺。

实验目的

(1)学会用先序创建一棵二叉树。

(2)学会采用递归算法对二叉树进行先序、中序、后序遍历。 (3)学会打印输出二叉树的遍历结果。

实验内容

【问题描述】建立一棵二叉树,并对其进行遍历(先序、中序、后序),打印输出遍历结果。 【基本要求】

从键盘接受输入(先序),以二叉链表作为存储结构,建立二叉树(以先序来建立),并采用递归算法对其进行遍历(先序、中序、后序),将遍历结果打印输出。 【测试数据】

ABCффDEфGффFффф(其中ф表示空格字符) 则输出结果为 先序:ABCDEGF 中序:CBEGDFA 后序:CGBFDBA 【选作内容】

采用非递归算法实现二叉树遍历。

实验步骤

(一)需求分析

1、在这个过程中,接受遍历的二叉树是从键盘接受输入(先序),以二叉链表作为存储结构,建立的二叉树。因此,首先要创建一棵二叉树,而这棵二叉树是先序二叉树。本演示程序中,集合的元素设定为大写字母ABCDEFG,输出的先序,中序,后序遍历分别为ABCDEGF,CBEGDFA,CGBFDBA。二叉树可以表示为:

接受的输入数据在进行递归的先序,中序,后序遍历后,分别将结果打印出来。

2、在程序运行的过程中可以看到,以计算机提示用户执行的方式进行下去,即在计算机终端上提示“输入二叉树的先序序列”后,由用户在键盘上输入ABC##DE#G##F###,之后相应的选择遍历及遍历结果显示出来。

3、程序执行的命令包括:首先是二叉树的先序序列被创建输入,其次是对输入进去的先序序列有次序的进行先序,中序,后序遍历。最后是打印出二叉树的遍历结果。 4、测试数据

(1)在键盘上输入的先序序列ABC##DE#G##F### (2)先序遍历结果ABCDEGF

(3)中序遍历结果CBEGDFA (4)后序遍历结果CGBFDBA

(二)概要设计

1、为实现上述程序功能,应以二叉树定义的相关操作和二叉树递归遍历的相关操作为依据。有关以二叉链表作为存储结构,建立二叉树的操作为:

typedef BTNode *BTree; //定义二叉树的指针 BTree CreatBTree(void) { BTree T; char ch; if((ch=getchar())=='#') return(NULL); //读入#,返回空指针 else{ T=(BTNode *)malloc(sizeof(BTNode)); //分配空间,生成结点 T->data=ch; T->lchild=CreatBTree(); //构造左子树 T->rchild=CreatBTree(); //构造右子树 return(T); } }

2、而有关先序、中序、后序遍历的递归操作为: void Preorder(BTree T) //先序遍历 { if(T){ printf("%c",T->data); //访问结点 Preorder(T->lchild); //先序遍历左子树 Preorder(T->rchild); //先序遍历右子树 } }

void Inorder(BTree T) //中序遍历

{ if(T) { Inorder(T->lchild); //中序遍历左子树 printf("%c",T->data); //访问结点 Inorder(T->rchild); //中序遍历右字树 } }

void Postorder(BTree T) //后序遍历 { if(T) { Postorder(T->lchild); //后序遍历左子树 Postorder(T->rchild); //后序遍历右子树 printf("%c",T->data); //访问结点 } }

3、本程序包含的模块 (1)结点单元模块 (2)构建先序二叉树模块 (3)二叉树遍历模块 (4)主程序模块

各模块之间的调用关系如下:

(三)详细设计

1、元素类型,结点类型和指针类型

typedef struct node { char data; //二叉树的元素类型 struct node *lchild; struct node *rchild;

}BTNode; //自定义二叉树的结类型 typedef BTNode *BTree; //定义二叉树的指针

2、定义类型之后,要以二叉链表作为存储结构,建立二叉树(以先序来建立)。

BTree CreatBTree(void) { BTree T; char ch; //定义输入的数据类型 if((ch=getchar())=='#') //支持在键盘上输入先序二叉树 return(NULL); //读入#,返回空指针

对于二叉树的先序输入,在输入中要注意的是对于空指针的把握,由于是先序输入,在输入时要在确定的位置输入“#”号,否则先序二叉树将不完整。 else{ T=(BTNode *)malloc(sizeof(BTNode)); //分配空间,生成结点 T->data=ch; T->lchild=CreatBTree(); //构造左子树 T->rchild=CreatBTree(); //构造右子树 return(T); } }

当输入的叶子结点完整之后,要return(T),

否则输入将一直持续

下去不能跳出来。在程序的设计过程中,在适当的位置插入#对于二叉树的遍历有着十分重要的作用,因此要明白二叉树的先序创建过程如何运行。

3、对于二叉树进行先序、中序、后序的遍历。

void Preorder(BTree T) //先序遍历 { if(T){ printf("%c",T->data); //访问结点 Preorder(T->lchild); //先序遍历左子树 Preorder(T->rchild); //先序遍历右子树 } }

这个是先序遍历,先序遍历与中序遍历,后序遍历相似,都是以不同顺序访问子树及结点。先序遍历先访问根节点,先序遍历左子树,再先序遍历右子树。而中序遍历是中序遍历左子树,访问根节点,中序遍历右子树。后序遍历是后序遍历左子树,后序遍历右子树,后序遍历根节点。三个遍历虽说顺序不一致,但是在程序的编写上有很多可以相通的地方。以下分别是中序、后序的程序:

void Inorder(BTree T) //中序遍历 { if(T) { Inorder(T->lchild);

//中序遍历左子树 printf("%c",T->data);

//访问结点

Inorder(T->rchild);

//中序遍历右字树

}

}

void Postorder(BTree T) //后序遍历 { if(T) { Postorder(T->lchild); //后序遍历左子树 Postorder(T->rchild); //后序遍历右子树 printf("%c",T->data); //访问结点 } }

4、主程序模块的链接。在这个模块中,不仅要实现二叉树先序序列从键盘的输入,还要实现选择三个遍历的输出。主函数的作用旨在使每个程序模块能够链接在一起,调用各个函数以实现最终的目的。

void main() { BTree root; //数的根结点 int i; //可供选择的整型变量i printf("\n"); printf("请输入二叉树的先序序列,用#代表虚结点:"); root=CreatBTree(); //返回根结点 do{ //循环语句

printf("********************SELECT********************\n"); printf("\t1:先序遍历\n"); printf("\t2:中序遍历\n"); printf("\t3:后序遍历\n"); printf("\t0:Exit\n"); printf("\t*********************************************\n"); scanf("%d",&i);//输入菜单序号

switch(i) { case 1:printf("先序遍历结果为:"); Preorder(root); break; case 2:printf("中序遍历结果为:"); Inorder(root); break; case 3:printf("后序遍历结果为:"); Postorder(root); break;

在这三个选择中,充分调用了先序、中序、后序遍历函数,选择1、2、3数字实现对三个遍历的输出打印。 default:exit(1); } printf("\n"); } while(i!=0); }

5、函数的调用关系图反映了演示程序的层次结构:

(四)调试分析

1、实验涉及的部分包括用二叉链表创建先序二叉树,对二叉树进行三种遍历,最后是对三种遍历结果进行打印。在做这个实验的过程中,我们首先最先碰到的问题是用二叉链表存储先序二叉

树,由于对二叉树存储的不深入了解,我们在输入数据时,只能对其无限输入,并不能及时的终止,导致的结果是程序停止不了,运行不下去。不能返回的问题困扰了我们很久,在这个过程中,我们还尝试了一些用栈来对其进行存储,通过一遍遍的摸索,最终找到了正确的方法。在这个过程中,我们也对二叉树的存储有了更为深刻的了解,相信这在我们以后的学习中也有很大的帮助。

2、在实验过程中,我们还有尝试了非递归的算法对于二叉树的遍历,递归算法和非递归算法各有千秋,产用递归算法更为简单明了。

3、根节点的运用没有得到合理的开发,在主程序的链接中,创建二叉树,返回根节点。接着是一个do循环对于选择三种遍历结果的打印输出和退出操作,在开始的程序设计阶段没有发挥作用,前期使用的是while和swith语句,没有返回根结点,造成算法的运行不能有序进行下去。

4、刚开始是忽略了一些细节问题,对于元素类型,结点类型的定义没有认真检查,程序前期运行过程中有很多的失误,导致了效率低下。今后一定要重视确定参数的变量和赋值属性的区别和标志。

5、程序的设计基本是由一个个子模块联系到一起,由于前期没有将这个程序的大致模型框架构架好,子模块之间的联系在主程序中就出现了一些问题,因此在以后的实验过程中,要首先构造大框架更有利于子模块的链接。

(五)用户手册

1、本程序的运行环境为 DOS 操作系统,本程序执行文件为“执行二叉树建立与遍历.exe”。 2、进入程序运行后会有说明指示

首先创建二叉树按照完全二叉树的先序序列输入,以回车键结束,程序主界面就会形成:

3、按照要求输入各个功能的命令,程序接受命令后立即执行并且显示相应的结果。

(六)测试结果

(1)首先二叉链表存储(以先序创建)键盘输入

(2)选择数字“1”,先序遍历:

(3)选择数字“2”,中序遍历:

中南民族大学管理学院学生实验报告

(4)选择数字“3”后序遍历:

(九)附录:源程序清单

#include<stdio.h> #include<stdlib.h> #include<string.h>

//***************************************************** typedef struct node { char data; //二叉树的元素类型 struct node *lchild; struct node *rchild;

}BTNode; //自定义二叉树的结点类型 //***************************************************** typedef BTNode *BTree; //定义二叉树的指针 BTree CreatBTree(void) { BTree T; char ch;

if((ch=getchar())=='#') //支持在键盘上输入先序二叉树 return(NULL); //读入#,返回空指针 else{ T=(BTNode *)malloc(sizeof(BTNode)); //分配空间,生成结点 T->data=ch; T->lchild=CreatBTree(); //构造左子树 T->rchild=CreatBTree(); //构造右子树 return(T);

}

}

//****************************************************** void Preorder(BTree T) //先序遍历 { if(T){ printf("%c",T->data); //访问结点 Preorder(T->lchild); //先序遍历左子树 Preorder(T->rchild); //先序遍历右子树 } }

//***************************************************** void Inorder(BTree T) //中序遍历 { if(T) { Inorder(T->lchild); //中序遍历左子树 printf("%c",T->data); //访问结点 Inorder(T->rchild); //中序遍历右字树 } }

//*************************************************** void Postorder(BTree T) //后序遍历 { if(T) { Postorder(T->lchild); //后序遍历左子树 Postorder(T->rchild); //后序遍历右子树

printf("%c",T->data); //访问结点 } }

//************************************************** void main() { BTree root; //二叉树的根结点 int i; printf("\n"); printf("请输入二叉树的先序序列,用#代表虚结点:"); root=CreatBTree(); //返回根结点 do{ //do做循环打印遍历结果 printf("********************SELECT********************\n"); printf("\t1:先序遍历\n"); printf("\t2:中序遍历\n"); printf("\t3:后序遍历\n"); printf("\t0:Exit\n"); printf("\t*********************************************\n"); scanf("%d",&i);//输入菜单序号 switch(i) { case 1:printf("先序遍历结果为:"); Preorder(root); break; case 2:printf("中序遍历结果为:"); Inorder(root); break; case 3:printf("后序遍历结果为:"); Postorder(root); break; default:exit(1); }

}

printf("\n"); }

while(i!=0);

实验结果分析

通过我们团队的努力,我们的二叉树建立与遍历实验完成了,在这个实验过程中,我们碰到了一些问题,比如说二叉树的存储没有能够准确返回,主函数与模块函数之间没有实现很好的连接造成调试程序上用了很多时间。忽略了一些细节问题,对于元素类型,结点类型的定义没有认真检查,程序前期运行过程中有很多的失误,导致了效率低下。但是我们充分发挥了团队的力量,依次解决了这些问题,实验结果的正确性也得到了验证。虽说可能仍存在一些不足之处,我们也会虚心接受,在过程中力求做到尽可能的完善。而在此次的实验过程中,和以前的课程设计有一些不同之处,首次产用团队合作的方式完成实验,我们也在这个过程中体会到了团队合作的好处,大家积极分享彼此的经验,在分工的基础上合作,在合作的前提下创新。学到了很多课本上没

有的知识,也在团队合作过程中提升了自身的能力。

指导教师批阅:

指导教师:

年 月 日

本文来源:https://www.bwwdw.com/article/uabi.html

Top