数据结构实验报告
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
实验一线性表的顺序存储和链式存储
实验时间2012/10/8 星期一第六周一、实验目的及要求
(1)掌握线性表的顺序存储和链式存储结构
(2)熟练地利用链式存储结构或者顺序存储结构实现线性表的基本操作
(3)能熟练地掌握链式存储结构或顺序存储结构中算法的实现二、实验内容
解决约瑟夫问题,设有n个人按1、2、3、...、n的顺序围成一圈,现在从第s个人开始按1、2、3、...、m的顺序报数,数到m 的人出圈,接着从出圈的下一个人开始重复此过程,直到所有的人出圈为止。
三、算法实现
(一)、运用链式存储结构实现算法
⑴先定义一个链表节点的结构体,结构体中data的值用来表示该节点所表示的人是否出圈,*next指针指向下一节点;
⑵用一个函数初始化一个n个节点的链表,并把最后一节点的*next指针指向头结点,以便形成循环链表。
⑶用一函数将指针所指向的整个循环链打印输出。
⑷用一函数模拟循环报数出圈:函数中采用三重循环,外层循环为报数出圈的人数,即第L个人出圈后停止报数;中层循环为报数的数值,即循环M次直到报到M的人出圈;内层循环用来排除已
经出圈了的人,报数时遇到节点data值为0(即已经出圈了的人)则循环,直到节点data值为1(即未出圈的人)后退出本循环继续报数。
(二)、运用顺序存储结构实现算法
先定义顺序表的数据类型,然后将n个人的编号存入一个一维数组中,表的长度就是人数n,因此就可以用一维数组来代替顺序表。
算法的思想是先求出出圈人的编号,用一个临时单元保存它,然后从出圈人的后一个开始,直到最后一个,都按顺序向前移动一个位置,再将临时单元中的出圈人编号存入最后。
当这个重复步骤完成后,数组中存放的是出圈人的逆序列。
本题中,围圈的人数n、出圈的报数号m、开始报数的位置s在程序中预先给定为10、3、2。
当然,也可以从键盘临时输入。
四、实验总结与感悟
一开始编写这个程序时,存储结构我用的并不是循环链表,而是一维数组。
原理基本和用循环链表编写的差不多,但为了达到循环“报数”的目的,在“报数踢人”函数里的循环嵌套内还得加一条判断语句,作用是当数到最后一人时又从数组起始位置开始数。
最后实现的功能都是一样的。
但后来使用循环链表之后,省去了这一条判断语句,没报一次数,指针尽管指向下一结点就可以了,方便了很多。
为了具体的观察每次报数的情况,我在“报数踢人”函数里的外层循环下将链表的数据域输出。
这样,每当一个人出圈后,就会将当次情况输出显示了。
实验二多维数组的应用
实验时间2012/10/19 星期五第七周一、实验目的及要求
(1)掌握多维数组数据类型的描述及特点
(2)掌握多维数组的顺序和链式两种存储结构的特点及算法描述(3)掌握稀疏矩阵在两种不同存储结构上的算法实现
二、实验内容
(1)创建空的稀疏矩阵十字链表存储结构
(2)稀疏矩阵十字链表的数据输入
(3)稀疏矩阵十字链表的数据显示
(4)稀疏矩阵十字链表的数据查找
(5)用三元组实现稀疏矩阵的转置
三、算法实现
先定义各个需要的函数组成部分,然后依次构建四个子函数,分别是新建十字链表、显示十字链表、输入链表元素、查找链表元素;然后是通过主函数对各个子函数的调用,来实现题目的目的。
整个程序中主要用到指针定位,for循环,还有switch选择语句。
其中对指针的运用很难,很难定位指针,而且指针太多,繁杂。
实验步骤:
1.进入编程环境,建立一新文件;
2.先定义稀疏矩阵的类型,用子函数建立十字链表,最后在主函数中调用。
3.将稀疏矩阵的三元组按行优先从键盘输入,然后调用转置算
法,实现稀疏矩阵转置。
4.编译运行程序,观察运行情况和输出结果。
部分实验代码:
⑴三元组顺序表结构的定义
#define maxsize 255
typedef int elemtype;
typedef struct
{
int i,j;
elemtype e;
}
triple;
typedef struct
{ int mu,nu,tu;
triple data[maxsize];
}
tsmatrix;
⑵矩阵的转置运算
void transposesmatrix(tsmatrix M,tsmatrix T) { int q,col,p; T.mu=M.nu; T.nu=M.mu; T.tu=M.tu; if(T.tu!=0)
{ q=1;
for(col=1;col<=M.nu;++col)
四、实验结果及感悟
本次试验是稀疏矩阵十字链表的存储,通过这个实验,我们可以更好的掌握稀疏矩阵十字链表存储的方法以及稀疏矩阵的显示,查找等一些基本算法。
在实验中我们对要定义的子函数进行声明,后建立新的存储结构,再后定义不同的子函数来实现稀疏矩阵十字链表的建立、显示、输入数据、查找等基本运算。
在实验编程中,我遇到了很多问题,因为课上有些内容老师还没有仔细的分析,所以有部分内容还是很生疏,自己看的效率也没有听老师接受的多,经过网上搜索和同学讨论等途径,才勉强把问题解决了,通过这次实验编程,也让我了解到了好好听老师课的重要性,还有课前预习,预习中剩下的还有的不明白得地方,在上课老师讲课过程中可以更加有取舍的听。
实验三二叉树的遍历和应用
实验时间2012/10/29 星期一第九周
一、实验目的及要求
1.掌握二叉树的数据类型描述及二叉树的特性
2.掌握二叉树的链式存储结构(二叉链表)的建立算法
3.掌握二叉链表上二叉树的基本运算的实现
二、实验内容
1.用递归实现二叉树的先序、中序、后序三种遍历
2.用非递归实现二叉树的先序、中序、后序三种遍历
3.实现二叉树的层次遍历
4.将一颗二叉树的所有左右子树进行交换
三、算法实现
定义二叉树类和队列类,创建二叉树的数使用书上的递归函数思想,先序、中序和后序三种方式遍历该二叉树的函数方法也是用的是递归函数。
层次遍历时,利用了队列的性质特征先让双亲节点入队列,再进行出队列操作,对出队列节点进行访问,再判断出队列节点的左右孩子是否为空,不为空,就先后让左右孩子入队列,重复以上过程直到队列为空,则访问的结果顺序就为层次遍历。
例:先序递归遍历二叉树:
voidvoidvoidvoid Preorder
(structstructstructstruct BitreeNode *p)
{
ifififif (p!=NULL)
{
printf("%c",p->data);
Preorder( p->lchild );
Preorder(p->rchild );
}
四、实验结果及分析
通过学习数据结构,发现数据结构包括线性结构、树形结构、图状结构或网状结构。
线性结构包括线性表、栈、队列、串、数组、广义表等,栈和队列是操作受限的线性表,串的数据对象约束为字符集,数组和广义表是对线性表的扩展:表中的数据元素本身也是一个数据结构。
除了线性表以外,栈是重点,因为栈和递归紧密相连,递归是程序设计中很重要的一种工具。
树状结构中的重点自然是二叉树和哈弗曼树了。
对于二叉树的很多操作都是基于对二叉树的遍历,掌握了如何遍历,很多问题也就迎刃而解了,比如对二叉树结点的查找访问、统计二叉树中叶子结点的数目、求二叉树的深度等。
哈弗曼编码也有着很广泛的应用。
对于图状结构,主要学习图的存储结构及图的遍学习算法的目的是利用算法解决实际问题。
会写课本上已有的算法之后,可以借其思想进行扩展,逐步提高编程能力。
比如数值转换,括号匹配的检验,检验平衡二叉树等。
实验四图的遍历及应用
实验时间2012/11/9 星期五第十周
一、实验目的及要求
(1)掌握图的基本概念和邻接矩阵(表)的存储结构
(2)掌握图的邻接矩阵(表)存储结构的算法实现
(3)掌握图在邻接矩阵(表)存储结构上遍历算法的实现
二、实验内容
编写程序实现所给图的邻接矩阵表示及其基础上的深度和广度优先遍历。
三、算法实现
1.深度优先遍历(DFS)法:
1)初始化:
(1)置所有顶点“未访问”标志;
(2)打印起始顶点;
(3)置起始顶点“已访问”标志;
(4)起始顶点进栈。
2)当栈非空时重复做:
(1)取栈顶点;
(2)如栈顶顶点存在被访问过的邻接顶点,则选择一个顶点
①打印该顶点;②置顶点为“已访问”标志;③该顶点进栈;
否则,当前栈顶顶点退栈。
3)结束。
2.广度优先(BFS)法:
1) 初始化:
(1)置所有顶点“未访问”标志;
(2)打印起始顶点;
(3)置起始顶点“已访问”标志;
(4)起始顶点入队。
2)当队列非空时重复做:
(1)取队首顶点;
(2)对与队首顶点邻接的所有未被访问的顶点依次做:
①打印该顶点;②置顶点为“已访问”标志;③该顶点入队;否则,当前队首顶点出队。
3) 结束。
四、实验总结和感悟
图的存储结构有邻接矩阵、邻接表、十字链表等。
其中邻接矩阵和邻接表为图的主要存储结构。
图的邻接矩阵存储结构的主要特点是把图的边信息存储在一个矩阵中,是一种静态存储方法。
图的邻接表存储结构就是图的边信息的矩阵中全部非零元素的三元组的行指针数组结构的三元组链表,是一种顺序存储与链式存储相结合的存储方法。
二者各有利弊,具体应用时,要根据图的稠密和稀疏程度以及问题需求进行选择。
从空间性能上说,图越稀疏邻接表的空间效率相应
的越高。
从时间性能上来说,邻接表在图的算法中时间代价较邻接矩阵要低。
实验五内部排序实验
实验时间2012/11/26 星期一第十三周一、实验目的及要求
(1)掌握各种排序的基本思想
(2)掌握各种排序方法的算法实现
(3)掌握各种排序方法的优劣及花费时间的计算
(4)掌握各种排序方法适用的不同场合
二、实验内容
对六种排序:冒泡排序,直接插入排序,简单选择排序,快速排序,希尔排序,堆排序,算法进行比较,比较的主要内容是待排序文件中关键字的比较次数和移动次数。
三、算法实现
1.冒泡排序:相邻的两个元素进行比较,将小的调到前面,大
的调到后面。
2.直接插入排序:待排序的记录放在数组R[0…n-1]中排序过
程中某一时刻R被划分成两个子区间R[0…i-1] (有序
和)R[i…n-1](无序)。
直接插入的基本操作是将当前无序区
的一个记录R[i]插入到有序区R[0…i-1]中适当的位置。
3.简单选择排序:基本思想:在待排序的一组数据元素中选出
最小的一个数据元素与第一个位置的数据元素交换,然后在
剩下的数据元素当中再找最小的与第二个位置的数据元素交换,循环到只剩下最后一个数据元素为止。
4.快速排序:在待排序的数组的n个元素中取一个元素(一般
取第一个)将其移动到这样的位置,在其之前的元素的值都小于它,在其之后的元素都大于它。
这样是一趟快速排序,然后对数组的两个部分进行同样的操作。
直到每部分只有一个记录为止。
总之,每趟使表的第一个元素放在适当位置,将表两分,再对两子表进行同样的递归划分 直至划分的子表长度为1。
5.希尔排序:先取一个小于n的整数d1作为第一个增量,把
文件的全部记录分成d1个组。
所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插入排序,然后 取第二个增量d2<d1重复上述的分组和排序,直至所取的增dt=1(dt<dt-l<…<d2<d1) 即所有记录放在同一组中进行直接插入排序为止。
6.堆排序:首先将待排序的记录序列构造成一个堆,这时堆的
头结点既是最大元素,将其和最后一个记录交换。
然后将除了最后一个记录的记录序列再调整成堆。
这样就找出了次大的元素。
以此类推,直到堆中只有一个记录为止。
调整堆的思想是将待调整的结点的左右孩子进行比较选出较大的一个和待调整结点进行比较,若待调整结点小则交换,否则调整结束。
四、实验总结与感悟
内部排序的算法中,在平均情况下,比较次数从少到多依次为:堆排序、快速排序、希尔排序、直接插入排序、冒泡排序、简单选择排序 移动次数从少到多依次为:简单选择排序、堆排序、快速排序、希尔排序、直接选择排序、冒泡排序。
通过对冒泡排序、直接插入排序、简单选择排序、快速排序、希尔排序、堆排序这几种内部排序算法进行比较,能够加深我们对这些排序的基本思想及排序算法的掌握和理解。
通过该题目的设计过程可以加深理解各种数据结构的逻辑结构、存储结构及相应上运算的实现。
进一步理解和熟练掌握课本中所学的各种数据结构。
学会如何把学到的知识用于解决实际问题,培养我们的动手能力。