简介:华南农业大学数据结构上机实验指导书,面向该校计算机及相关专业学生,用于配套数据结构课程的上机实践训练。文档以实验形式系统展开,覆盖线性表、堆栈、队列、模式匹配与二叉树五大主题;每个实验均设有实验目的、实验内容和实验报告三个模块,从基础概念到操作实现层层递进。其中,线性表实验包含数组与链表两种实现方式,堆栈与队列实验涉及压入/弹出、入队/出队等核心操作,模式匹配实验则对比暴力算法与KMP算法的时间空间复杂度。整份资源附有完整参考答案,便于学生在实践中对照校验、查漏补缺。资源为单个doc文档,体积仅639KB,排版简洁,适合打印或电子阅读,既可课上同步练习,也可课后自学巩固。该资源已有293人学习下载,对正在学习数据结构、需要系统上机训练的初学者具有较高参考价值。完成这些实验,可帮助读者掌握常用数据结构的存储原理、操作方法及复杂度分析,为后续算法与程序设计学习打下扎实基础。
1. 一份“附答案”的上机指导书,为什么比教材更值得啃
“数据结构上机实验指导书(附答案)”这类文档,在很多人的U盘里躺了一整个学期,直到期末前才被翻出来。它既不是教材,也不是习题册,而是老师把“动手验证抽象概念”这件事拆成了八个到十个实验:从顺序表、链表一路写到排序与查找。华南农业大学这份版本的特点是实验要求写得很具体,每个实验给出可编译的参考代码,答案部分又让你在写不出来的时候有一粒后悔药。适合两类人:一类是上课听得懂、一到上机就无从下手的初学者;另一类是想用实验反推考点、顺带准备考研数据结构的人。前者把它当教程,后者把它当题库。
2. 从目录看实验体系:线性表到排序,指导书到底让你练什么
拿到任何一份数据结构上机实验指导书,我做的第一件事不是翻代码,而是看目录。目录几乎是教学大纲的镜像,能直接看出这门课在哪些知识点上愿意花时间,哪些只是带过。
2.1 实验编排的逻辑:数据结构c语言版的教学骨架
常见的实验编排顺序是这样的:先线性表,再栈和队列,再串和数组,然后树和图,最后查找与排序。对应到数据结构c语言版教材,就是每一章后面安排一个上机任务。华南农业大学这份指导书的实验划分也基本沿用了这个结构。
线性表的两个实验放在最前面:顺序表和链表。顺序表练的是“存储密度”和“随机访问”,链表练的是指针操作和插入删除的灵活性。这两个实验决定了你后面所有实验的代码习惯——比如是否记得释放内存、是否区分逻辑位置和物理下标。接下来是栈和队列,经典题目不外乎括号匹配、表达式求值、循环队列。再往后是串的KMP算法、数组的稀疏矩阵三元组表示,然后是二叉树的三种遍历和哈夫曼树,图的邻接矩阵与邻接表存储、DFS与BFS、最小生成树或最短路径,最后是各种排序算法的比较。
这个顺序不是随便排的。每个实验都在给下一个实验做铺垫:链表实验让你理解指针,树实验的递归遍历才能写得出来;图的邻接表本质上就是“数组加链表”的组合结构;排序实验又反过来检验你对数组下标的敏感程度。如果前面的实验靠抄答案混过去,后面的实验就会越走越吃力。
2.2 八个核心实验模块与验收点对照表
把指导书里的实验模块整理成一张表,按“实现要点”和“常见验收点”两列来看,能很快定位每个实验的核心矛盾。
| 实验模块 | 核心算法 | C语言实现要点 | 常见验收点 |
|---|---|---|---|
| 顺序表 | 插入、删除、查找 | 动态数组、容量扩容、元素后移 | 越界检查、插入位置为0或length时的处理 |
| 链表 | 单链表建立、反转、合并 | 头指针/头结点、malloc与free | 空链表操作、内存是否泄漏 |
| 栈和队列 | 括号匹配、表达式求值、循环队列 | 栈顶指针、队空队满判断 | 链栈与顺序栈的选择、队列判空条件 |
| 串 | KMP模式匹配 | next数组的推导 | 模式串与主串边界,next[0]的约定 |
| 树 | 先序/中序/后序遍历、哈夫曼树 | 递归遍历、二叉树链表存储 | 递归出口、空树处理、带权路径长度 |
| 图 | 邻接矩阵/邻接表、DFS/BFS | 图的两种存储结构转换 | 非连通图的遍历、最小生成树权值之和 |
| 查找 | 顺序查找、折半查找、哈希 | 有序表折半、冲突处理 | 折半查找的边界条件、哈希表负载因子 |
| 排序 | 直接插入、冒泡、快速、堆、归并 | 交换与移动次数、稳定性 | 输入有序/逆序时的表现、比较次数 |
上机验收时最常见的检查动作,是老师随机挑一个测试数据让程序现场跑,然后问一句“这个算法的时间复杂度是多少”。如果你只是照着答案敲了一遍,却没有理解每个算法在不同输入下的表现差异,这一问就很容易卡壳。所以这张表里我特别加了一列“常见验收点”,准备上机前对着它自测一遍,比多敲三遍代码都管用。
2.3 图与数组、查找与排序:哪些实验在期末和考研里反复出现
如果说前面几个实验是在打基础,那图和数组、查找与排序这两块,就是期末和考研数据结构分别命题的高频区。考研408的“图和数组”大题,经常考邻接矩阵与邻接表的互相转换,或者给出一个图的存储结构让你写出遍历序列。指导书里对应的实验如果认真做过,看这类题目会有一种“这我上过机”的感觉,而不是停留在背定义的层面。
查找和排序就更明显了。期末笔试爱考排序过程的推导——给一串初始序列,写出每趟冒泡或每趟快速排序之后的结果。这类题靠背是背不住的,因为在纸上写过程的时候,很容易在元素交换那一步出错。我一般建议把指导书里排序实验的测试数据抄下来,手动推一遍,再跑程序对一遍输出。两边对上了,才算真正掌握。数据结构排序算法这块是所有上机实验里“性价比”最高的部分——代码量不大,却能同时覆盖笔试和机试。
3. 照着指导书跑通一个实验:从建工程到看测试点的六步流程
拿到指导书里的任何一个实验,我一般按六步走:读任务书、搭骨架、写核心、补测试、跑调试、写验收记录。前面三步决定你能不能跑通,后面三步决定你能拿多少分。
3.1 第一步:读实验任务书,先圈出“不允许改”的接口签名
数据结构实验的题干里最容易被忽略的是函数签名。比如“设计一个函数Status ListInsert(SqList &L, int i, ElemType e)”,这里的SqList、i、e,以及返回值Status,都是验收的约定。有的同学觉得函数名无所谓,自己改了照样能跑,结果验收时老师的测试代码一替换就编译失败,当场翻车。
我的习惯是先把任务书里的类型定义和函数声明抄到注释里。比如顺序表实验,在代码文件最上方写清楚:
#define MAXSIZE 100 // 顺序表的最大容量 typedef int ElemType; // 元素类型,可换成结构体 typedef struct { ElemType data[MAXSIZE]; int length; // 当前长度,初始为0 } SqList; // 接口约定:i 是逻辑位置,从1开始计数,不是数组下标 Status ListInsert(SqList *L, int i, ElemType e);这段注释看起来简单,但它其实是整个实验的“契约”。逻辑位置从1开始还是从0开始,直接影响插入时元素后移的起点。很多运行结果不对的问题,查到最后都是这个约定没对齐。所以第一步不是写代码,是把这些约束找出来。
3.2 第二步:搭骨架,先让程序能编译
不要去追求一口气把算法写完。先写一个最小骨架:结构体定义、函数声明、main函数里调用一下,然后编译一次。这样能把“语法错误”和“算法错误”分开排查。顺序表插入的一个最小骨架长这样:
#include <stdio.h> #include <stdlib.h> #define MAXSIZE 100 typedef int ElemType; typedef int Status; typedef struct { ElemType data[MAXSIZE]; int length; } SqList; Status ListInsert(SqList *L, int i, ElemType e) { if (L->length >= MAXSIZE) return 0; // 表满 if (i < 1 || i > L->length + 1) return 0; // 位置非法 for (int j = L->length; j >= i; j--) { L->data[j] = L->data[j - 1]; // 从后往前移 } L->data[i - 1] = e; L->length++; return 1; } int main() { SqList L; L.length = 0; ListInsert(&L, 1, 10); ListInsert(&L, 2, 20); for (int i = 0; i < L.length; i++) { printf("%d ", L.data[i]); } return 0; }这段代码里有两个关键点。第一,函数参数用的是SqList *L,对应C语言里“引用传参”的写法。在C++里可以直接写SqList &L,但C语言没有引用,必须用指针,所以函数内部访问成员要写L->length而不是L.length。很多C语言版本的上机指导书默认你用C++的编译器写C语法,这里容易混。第二,插入位置i是从1开始的逻辑位置,所以数组中实际要移动的起点是i-1。这个换算关系是顺序表实验最常见的失分点。
3.3 第三步:用指导书的测试数据自测,再补三种异常输入
骨架能编译之后,先别急着炫技,用指导书给的输入输出样例跑一遍。顺序表实验的样例通常是这样的:初始表1 2 3,在第2个位置插入4,得到1 4 2 3。这不叫测试,叫“确认例程没写歪”。
真正的测试在样例之外。我一般会补三种输入:空表插入、越界插入、删除不存在的元素。比如上面那个ListInsert,空表时L->length为0,插入位置i=1应该成功;如果代码里没处理L->length + 1这个上限,空表插入就直接崩了。越界插入同理,i=0或i=length+2时应该返回0而不是悄悄写进数组。这三种边界测试的数据可以列在实验报告里,作为“异常处理”的证明。
3.4 第四步到第六步:编译、调试、验收记录一条线
编译时要开警告选项。在Linux下用gcc的话,我一般这样编译:
gcc -Wall -g -o sqlist sqlist.c gdb ./sqlist-Wall打开所有警告,-g加入调试信息。很多同学写C程序从不看警告,结果变量未初始化、函数声明缺失这些问题全被忽略,到了验收时换个编译器就编译不过。-Wall开之后,哪怕只多一个warning,我也会修掉再往下走。
调试时最常用的命令是break、print、next。在ListInsert里打一个断点,单步看元素后移的过程,比在大脑里模拟三遍都清楚。最后一步验收记录也很重要:把测试用例、预期输出、实际输出、是否通过列一张表,打印出来附在报告后面。这份记录既是写给老师看的,也是写给未来的自己看的——期末复习时扫一眼就知道哪些边界还没吃透。
4. 实验报告怎么写到让老师愿意给高分
上机实验报告往往是数据结构课里最容易被敷衍的作业。不少人觉得程序跑通了就完事,报告随便贴两张截图交上去。但按多数课程的做法,实验报告占了实验成绩的一半以上,而实验成绩又要计入总评。认真写报告的人,哪怕代码写得糙一点,分数往往比代码跑得飞快但报告两页纸的人高。
4.1 报告四段式:问题描述、设计、测试、总结
数据结构实验报告最稳妥的结构是四段式。第一段“问题描述”把题目要求用自己的话写一遍,把输入输出的限定条件列清楚。注意不要抄题,老师最讨厌看到一字不差的题目复制。第二段“设计”是核心:给出数据结构定义,画出流程图或写出算法思路,再写复杂度分析。这一段要回答一个关键问题:为什么选择这种存储结构、这种算法。
第三段“测试”就是我在3.4节里提到的验收记录表。第四段“总结”写你踩了什么坑、怎么解决的。这四段下来,一份报告大概三到四页,既不到注水的程度,又能把该说的说清楚。对应的模板大概是这样:
| 段落 | 内容要点 | 篇幅建议 |
|---|---|---|
| 问题描述 | 用自己的话复述需求,列出输入输出约束 | 5~8行 |
| 设计 | 存储结构定义、算法流程图、复杂度分析 | 1~2页 |
| 测试 | 用例表、运行结果、异常输入测试 | 半页到一页 |
| 总结 | 遇到的错误、排查过程、改进方向 | 8~12行 |
4.2 验收时老师最常问的三个问题
上机验收和期末考试不一样,它考的是“你亲手写过代码之后的理解”,所以问的问题大多是围绕着代码的现场追问,需要能够顺着代码讲清楚设计思路。
第一个问题是“为什么用这个存储结构”。比如顺序表实验,为什么用数组而不用链表?答案要说到“随机访问是O(1),但插入删除是O(n)”这个层面。第二个问题是“时间复杂度是多少”。这个不能只背结论,最好能从代码里数出循环次数。第三个问题是“如果数据量变成一千万,程序会怎样”。这问的是空间和时间的扩展性。顺序表用MAXSIZE定长数组,容量满了就插入失败;如果预先分配的内存不够,就需要考虑动态扩容。
4.3 把参考答案变成“自己的设计说明”
指导书附的答案是教学级正确解法,直接贴进报告会被一眼看穿,而且也没法回答好追问。我的做法是看答案理清思路,然后合上不看,用自己的话重新组织一遍设计说明。重点换两个口吻:一是“我选择”,二是“为什么不”。
比如顺序表插入,参考答案里只有一行for (int j = L->length; j >= i; j--),但报告里可以写:“我选择从表尾开始往前移动元素,这样每个元素只需要移动一次,不会覆盖未处理的元素。”再补一句“这里不能用从前往后的顺序移动,否则后面的元素会被前面的覆盖掉。”这就是老师想看到的东西——不是代码本身,而是你理解算法的边界。
另一种写法是把复杂度分析写透。顺序表插入的平均移动次数是n/2,这里的n是当前长度还是最大容量,很多人说不清。在报告中明确写“设当前表长为n,移动次数期望值为n/2,时间复杂度O(n)”,并说明为什么和容量无关,这一问就算拿稳了。
5. 附答案的正确用法与三个避坑点
指导书附答案既是福利也是陷阱。答案在初学者手里是“抄作业的素材”,在会用的人手里是“验证思路的标尺”。区别不在于自律,而在于用法。这一章写几个血泪经验,基本是在实验课和期末复习里反复出现的坑。
5.1 照着答案敲了三遍,验收时换了个数据就翻车
现象:上机前把参考代码抄了一遍,运行结果和样例一致。验收时老师把一个测试数据从“2 3 4”改成“5 1 9”,程序直接越界崩溃,当场翻车。
原因:复制粘贴的过程没有调动思考,代码里的边界条件——比如插入位置等于表长加一、删除位置等于表长——从来没被真正理解过。样例能跑通,只是因为你碰巧没有踩到边界,不代表边界处理是对的。
解决:答案可以看,但必须在看懂之后“离答案重写”。具体说,拿到一个实验,先自己写一版,写不下去再翻答案对应的函数,看完了合上,把这个函数重新默写一遍,写完对拍,看差异在哪。这种“带限制的抄”比纯粹抄答案多花二十分钟,但验收时的存活率高很多。
5.2 doc文件在部分设备上排版错乱,表格串行
现象:指导书是.doc格式,在手机或部分Linux自带的文档查看器里打开,排版乱成一团,表格的线全是歪的,代码缩进也丢了。
原因:.doc是老式的二进制格式,不同办公软件对其兼容性参差不齐。手机上用第三方查看器打开,经常把表格和分页符解析错位。
解决:别用手机看这份文档。在电脑上用WPS或新版Microsoft Office打开,先另存为.docx格式再阅读。如果在Linux环境下,用LibreOffice打开后另存为docx或pdf,再把pdf拷到移动设备上看。另存之后表格错位的问题基本消失,代码缩进也保得住。这个坑影响不大,但确实有人在验收前一个晚上因为打不开文档而手忙脚乱。
5.3 答案代码与教材模板不一致时,以谁为准
现象:指导书答案里的单链表用了带头结点的方式,数据结构教材上用的是不带头结点,两个函数签名长得也不一样。照着教材敲,对上机题;照着答案敲,对不上教材例题。最后不知道该听谁的。
原因:同一个算法在不同教材上有不同约定。带头结点vs不带头结点、逻辑位置从0开始vs从1开始、返回状态用0/1还是true/false,这些差异在C语言版的各类教材里长期并存。
解决:第一次做实验时统一以指导书和老师课上强调的版本为准。既然上机验收由任课老师组织,那他的接口约定就是“标准答案”。把教材的版本作为对照参考,在报告里写一句“本实验采用带头结点方式,处理空表时头结点保持不变”,既解释了设计,又避免了矛盾。等到期末复习时再回过头来对比两种写法的差异,那时候你对数据结构的理解才完整。
5.4 报告雷同度过高,被判定为相互抄袭
现象:两个同学的实验报告代码一模一样,连注释和变量名都相同,被课程查重标出来,双双扣分甚至算零分。
原因:指导书附答案意味着所有同学手里都有同一份参考代码。直接复制粘贴,大家的报告自然高度雷同。而上机实验课的报告查重早已不是新鲜事,很多学校用文档相似度检查。
解决:不要整段复制答案。至少做到三点:变量名按自己的习惯改掉(比如把i改成pos,e改成value);删掉答案里用不到的多余注释,补上自己对关键步骤的解释;在“总结”段写自己实际遇到的问题。这样既保留了答案的正确性,又让报告体现出个人调试的过程。抄答案不丢人,抄得让老师一眼看出来才丢分。
5.5 只做指导书实验,期末和考研题还是不会做
现象:指导书上的实验全跑通了,代码也能默写,但期末试卷上的“给出中序和后序序列,要求还原二叉树”还是不会。考研真题里“带权图求最短路径并写出每一步的dist数组变化”更是无从下手。
原因:上机实验是验证算法的正确性,而笔试题是考察算法推导过程。这两者的能力不完全重合。程序跑通了,不代表你能在纸上把每一步的中间状态写出来。指导书的答案已经是“代码级”表达,但考试要的是“过程级”表达。
解决:做完每个实验后,手动推一遍算法过程。排序实验就拿着测试数据在纸上写每一趟排序的结果;图的实验就把邻接矩阵画出来,手动跑一遍Dijkstra或Prim,每次松弛操作都记录dist数组的变化。这个过程不需要开电脑,但它是把“代码理解”转化成“考点理解”的关键一步。考研数据结构里的大题,几乎都能在这份指导书的某个实验里找到原型,关键看你有没有把运行的中间状态看清。
6. 期末前两周,把指导书当成自己的刷题清单
期末复习时,很多人把教材从头翻到尾,然后发现什么都没记住。我期末时略过通读教材,直接用指导书的目录做复习提纲:每章挑一两个实验,按“能否脱稿重写”作为掌握标准。顺序表和链表能默写,说明线性结构过关;排序实验能把快速排序的partition过程在纸上画出来,就不用担心笔试的大题。这个方法的原理很简单——上机实验覆盖面基本就是考试范围,与其从四百页教材里找重点,不如把八到十个实验当成考点清单逐个击破。
验证自己的方法也顺手。第3.4节提过gdb,这里补一个技巧:用watch命令监控关键变量的变化,比如watch L->length,在插入和删除操作时观察它的变化时机。另一个常用工具是valgrind,检测malloc的内存是否全部释放。链表实验的“内存泄漏”问题在验收时看不出来,但valgrind一跑就原形毕露。
如果备战考研408,每个实验再对应一两个真题方向:树的遍历对应“由遍历序列还原二叉树”,图的实验对应“最小生成树和最短路径的手动推导”,排序实验对应“各排序算法的稳定性与比较次数”。指导书这样做成对照表,两周时间完全够用。我当年把链表反转的实验抄了三遍,结果期末上机写链式队列时指针指错,卡了半小时。后来学乖了,每次实验后强迫自己不看答案重写一遍,写不出来就翻指导书对应段落,写完再手动推一遍过程。这个习惯从数据结构课一直带到了考研复习,希望帮到你。
本文还有配套的精品资源,点击获取