简介:一套《数据结构与算法》期中练习题答案文档,适合高校计算机类专业学生用于期中复习、错题对照与核心概念自查。文档针对数据结构课程常见考点,系统给出基本概念、算法分析的时间与空间复杂度、抽象数据类型、线性结构、栈与队列、二叉树、稀疏矩阵等模块的答案,并完整收录选择题及单链表指针修改、C语言结构数组存储位置计算、循环队列出入队追踪、静态链表插入删除、稀疏矩阵三元组表等题型的解答过程;二叉树部分涵盖满二叉树与完全二叉树深度、结点数关系、结点编号和左右孩子定位等易错点,读者可直接对照题目逐题验证思路。资源为1个doc文件,压缩包共318KB。目前已有127人学习下载。文档对链表操作与稀疏矩阵存储给出了逐步推导与图示说明,不仅提供最终结果,还能辅助理解指针变化和三元组行列转换逻辑,适合备考阶段快速查漏补缺。
1. 数据结构与算法期中练习题答案:那份 doc 是打卡表,不是背诵稿
考前一周,很多同学会顺手搜一份《数据结构与算法期中练习题答案.doc》,盼着用标准答案把考点背熟。这个想法不算错,但用法基本是反的——答案可以帮你对结果,却没法帮你对思路。真正决定期中成绩的,是你会不会在考场上用十分钟解出一道二十分的算法设计题。这门课的核心是数据结构和算法,考的是你能否在给定的时间与空间约束下,选出合适的数据组织方式,并写出能跑通的处理流程。
这份答案文档的真正价值,在于它是一张考点打卡表:能告诉你在老师的出题权重里,哪些题型反复出现,哪些知识点只是点缀。你需要做的是把每道题的答案盖上,自己先推一遍,再回来核对思路而不是核对结果。这篇笔记按“考什么、怎么拆题、哪些坑、考前怎么练”来展开,适合正在准备期中考试的本科在读学生,也适合想在考研数据结构之前先过一遍基础的自学者。如果你正处于“背答案但心里没底”的状态,读下去,我们把推导过程补齐。
2. 期中考什么:六大知识模块、高频考点与复习动作
数据结构与算法期中考试的知识范围,不同学校有差异,但主体框架逃不出线性表、栈与队列、树、图、查找、排序这六大模块。很多练习题答案文档的排版就是按这个顺序组织的,因为教材章节本身就长这样。先放一张考点权重和题型对应表,后面每小节按“考点说明、易错提醒、复习动作”展开。
| 模块 | 常见题型 | 权重参考 | 高频考点 |
|---|---|---|---|
| 线性表与链表 | 选择、填空、算法设计 | 高 | 插入删除复杂度、链表逆置、倒数第 K 个节点 |
| 栈与队列 | 选择、填空、简答 | 中 | 循环队列判满、出栈序列合法性、KMP 手算 |
| 树与二叉树 | 选择、填空、构造、算法设计 | 最高 | 遍历序列还原、哈夫曼编码、BST 删除 |
| 图 | 选择、填空、画图、算法设计 | 中高 | 存储结构、DFS/BFS 序、最短路径、最小生成树、拓扑排序 |
| 查找 | 选择、填空、计算 | 中 | 折半查找判定树、哈希冲突处理、平均查找长度 |
| 排序 | 选择、填空、大题 | 高 | 复杂度、稳定性、快排/堆排/归并过程 |
2.1 线性表与链表:画图推导比背代码可靠
线性表的考点集中在顺序表和链表的操作区别。顺序表插入或删除一个元素,最坏情况要把后半段整体移动,是 O(n);链表只需要改指针,O(1),前提是你已经找到了目标位置。期中练习里最常见的一道选择题是“在长度为 n 的链表第 i 个位置插入的时间复杂度”,答案是 O(n),因为查找占了时间,改指针本身是 O(1)。这一层如果没想透,题目稍微变一下就会选错。
链表算法设计的固定套路也有迹可循。逆置、删除指定值节点、找倒数第 K 个节点,都是“双指针或三指针”问题。我一般会建议先用抽象的小图走一遍:A、B、C 三个节点,想清楚 pre、cur、next 三个指针怎么移动,每次把 cur 的 next 改向 pre,然后整体右移。你在草稿纸上亲手画三轮指针变化,比背十遍代码都管用,因为考场上你能复现的是“指针移动逻辑”,不是代码串。
易错点在头节点上。带头节点与不带头节点的处理方式不同:删除节点时,前者不用单独考虑第一个节点;后者必须用二级指针或虚拟头节点,否则删头时指针就断了。教材如果是严蔚敏的《数据结构(C 语言版)》,链表算法题的风格偏基础,通常只考逆置和合并,但头节点的坑年年有人踩。复习动作:花二十分钟,把“删除链表中所有值为 x 的节点”写成文字步骤,先写带头节点版,再写不带头节点版,对比差异。这一步做透了,链表大题就稳了。
2.2 栈、队列与递归:出栈序列判断与 KMP 手算
栈考后进先出,队列考先进先出,基础概念不难,难在组合。典型题:入栈序列 1 到 n,问某个出栈序列是否合法。判定方法是从头模拟:用一个栈模拟入栈和出栈,序列里的元素能全部出完就合法。手推时注意一个关键误区——入栈不一定等全部入完才出,边入边出才是常考点。比如先入 1、2,出 2,再入 3,出 3、1,这种拆开看更接近真实考试。
循环队列判满是期中填空的“钉子户”。如果用牺牲一个存储单元的做法,队满条件是 (rear+1)%MaxSize == front;如果用 size 字段记录长度,条件变成 size == MaxSize。两道题的答案看起来不冲突,但混着用结果就翻车。做题时先看题设给的是哪种结构,再套公式。表达式求值、括号匹配属于栈的应用,波兰式和逆波兰式偶尔出选择,记住运算符栈与后缀串两个核心组件就够了。
KMP 是重灾区。练习答案里通常只给 next 数组的最终值,这是最大的坑,因为没有推导过程你并不知道这个值怎么来的。拿一个短串,比如 ababaca,自己手推一遍 next 数组:next[1] 固定为 0,next[j] 看模式串前 j-1 个字符的最长相等前后缀长度,前缀和后缀都不能取整个子串。手推两遍之后,你会发现之前背的“部分匹配值”表直接从模式串本身就能算出来,不需要额外记忆。字符串匹配的暴力枚举算法放在这里一起复习,别把它当查找题记——暴力算法是最容易写出 O(n*m) 的答案,KMP 是把它优化到 O(n+m)。
2.3 树与二叉树:遍历序列还原是必考大题
树的考点密度在全课程里排第一,二叉树遍历又是地基。前序、中序、后序三种遍历对应的递归写法,轮廓是“访问时机不同”,本质都是先左后右。期中练习答案里最常见的是:给出前序和中序,还原二叉树并写出后序。解题步骤是定位根:前序的第一个节点是根,拿它在中序序列里切开,左边是左子树,右边是右子树,递归执行。这个题型的正确率取决于你是否每次递归都把区间边界写对,而不是记忆什么“固定套路”。
哈夫曼树是另一个高频构造题。求 WPL(带权路径长度)时记住:新节点的权重是子树权重之和,左右子树谁大谁小不影响 WPL 值。构造步骤是每次从森林里取两个最小权值的树合并,放回森林,重复直到只剩一棵树。选择题常在“哈夫曼编码是否唯一”上做文章——编码不唯一,但 WPL 唯一。如果你手上还有《大话数据结构》这类偏轻松的读物,路上翻翻可以加深理解,但它不覆盖全部考点,复杂的图算法还是得回到教材。
二叉搜索树删除在练习里不太出大题,但选择题会问:删除有两个孩子的节点时,用哪个节点替换?答案是中序前驱或中序后继。复习动作:手动画一棵五个节点的 BST,删除根节点,分别用前驱和后继替换各做一遍,比较树形差异。递归算法题的出口写法要单独练:空树返回那条语句,不能省略,也不能写在错误的位置。很多同学递归思路是对的,出口漏了导致栈溢出,这属于低级失分。
2.4 图:存储结构、遍历顺序与数据结构 408 图和数组的关联
图的考察集中在存储结构与遍历。邻接矩阵和邻接表各有优势:判断两顶点是否相邻,矩阵 O(1);遍历邻接点,邻接表 O(deg)。考研数据结构题库里,数组和图的组合经常以“用邻接表存储图”的形式出现,408 里的图和数组章节常拿它做综合题,但期中的要求没那么高,能画清楚存储结构、能写遍历序就够。
DFS 序考的是递归栈和访问标记数组的配合——每访问一个节点立刻标记,再遍历未访问的邻接点。BFS 序则需要队列:起点入队,出队时把未访问邻接点全部入队。这里有个细节:DFS 和 BFS 的输出序列是否唯一,取决于邻接点是否按特定顺序存储。如果题设没说邻接表按升序排列,序列可能不唯一,标准答案通常按升序假设,做题时先看条件,别默认。
最短路径和生成树的固定解法要分清:Dijkstra 适合单源非负权,Prim 适合稠密图的最小生成树,Kruskal 适合稀疏图。Kruskal 按边权升序逐个加边,加边时跳过于形成环的边;Prim 从一个顶点出发,每次选“连接已选顶点集与未选顶点集的最小边”。复习动作:手算一个五顶点七条边的图的 Dijkstra 表,边写边更新 dist 与 path。另外,拓扑排序的考点是“多个入度为 0 的顶点存在时,选择顺序由队列或栈决定”,别忘了初始把所有入度为 0 的顶点入队。练习册里如果出现 Tarjan 或匈牙利算法这类拓展内容,按选学对待,期中权重很低。
2.5 查找:折半判定树与哈希冲突处理要会手算
查找模块期中的高频计算是平均查找长度(ASL)。顺序查找 ASL 是 (n+1)/2,折半查找要用判定树来算:把有序数组画成平衡的判定树,ASL 等于每层节点数乘以层数的和,再除以节点总数。练习答案经常直接给结果,但考试允许你画判定树,画出来分就稳了。注意折半判定树不是堆排序里那种完全二叉树,别混,前者的形态由 mid 的取整策略决定。
哈希表是填空与计算题的固定嘉宾。线性探测法处理冲突时,槽位被占就往后走,走到表尾回绕到表头;链地址法是每个槽位挂一条链表。算成功 ASL 是每个关键字查找次数相加除以关键字数;算失败 ASL 是每个可能的哈希位置到第一个空位的探测次数相加,除以表长。这两个定义最容易混,题目给出哈希表让你算 ASL 时,先圈住题干里的“成功”和“失败”,再决定分子分母。哈希的冲突分布看起来有点玄学,但手算两遍就能找到规律,核心是把每个关键字的探测路径画出来。
2.6 排序:复杂度、稳定性与适用场景一张表说清
排序是练习答案里篇幅最大的部分,因为可出题的角度多。复杂度要背,但不只是背结论:快排平均 O(nlogn),最坏 O(n^2),归并稳定且额外空间 O(n),堆排时间复杂度稳定但常数大。选择题最爱挖的坑是“快排最坏发生在什么情况”——答案是有序或逆序时,因为每次基准划分都极度不均。这个推导过程比结论重要,如果只记得“快排不安全”,遇到变题就会选错。
稳定性判断题:值相同的元素排序后相对顺序不变。冒泡排序算法的 C++ 实现版本是很多习题册必收的题,一趟冒泡把最大值沉底;选择排序每趟选最小值,不稳定;归并排序是稳定里最容易被忽略的稳定。场景选择题:大数据量且要求稳定选归并;内存受限选堆排;大体量且无法全部装入内存选外部排序。
| 算法 | 平均复杂度 | 最坏复杂度 | 额外空间 | 稳定性 | 适合场景 |
|---|---|---|---|---|---|
| 冒泡排序 | O(n^2) | O(n^2) | O(1) | 稳定 | 小规模、教学演示 |
| 选择排序 | O(n^2) | O(n^2) | O(1) | 不稳定 | 数据量小、交换代价高 |
| 插入排序 | O(n^2) | O(n^2) | O(1) | 稳定 | 基本有序的数据 |
| 希尔排序 | 约 O(n^1.3) | O(n^2) | O(1) | 不稳定 | 中等规模 |
| 快排 | O(nlogn) | O(n^2) | O(logn) | 不稳定 | 默认首选 |
| 归并排序 | O(nlogn) | O(nlogn) | O(n) | 稳定 | 要求稳定的场景 |
| 堆排序 | O(nlogn) | O(nlogn) | O(1) | 不稳定 | 内存受限 |
| 计数/桶排 | O(n+k) | O(n+k) | O(k) | 稳定 | 数据范围小 |
复习动作:用六个不同数字,手写快排第一趟的划分结果,再和参考答案对比。排序章节的答案文档有时带完整代码,建议自己编译运行一遍,因为只看代码运行结果,对排序过程的理解提升非常有限。
3. 把练习题答案变成解题模板:选择题、填空题与算法题三路拆解
练习答案文档的正确用法是“对题型”,不是“对答案”。不同题型的备考策略完全不同:选择题讲速度和判断,填空题讲边界条件,算法设计题讲结构。这一章把三种题型的拆解方法分开讲,每部分都有可以照着练的动作。
3.1 选择题:排除法、复杂度判断与“绝对词”陷阱
选择题常考两类:理论判断与复杂度计算。复杂度计算有个固定流程:第一步看循环变量是倍增还是线性递增,线性递增看层数,倍增如 n/=2 看 log;第二步检查循环体内有没有改步长或跳过条件;第三步递归函数写递推式,展开到能定性为止。举个例子:for(i=1;i<=n;i++) 里套一层 for(j=i;j<=n;j*=2),内层是 log 级别,但外层 i 在变,总次数是逐项求和而不是简单相乘。练习答案往往只给最终复杂度,不给你展开式,这是选择题错一半的根源。
排除法有个小经验:说法里出现“一定”“必须”“唯一”这类绝对词,多半需要细究。例如“任何情况下哈希表的查找都是 O(1)”,明显错,最坏情况冲突严重会退化到 O(n);又比如“堆排序在任何数据分布下都比快排快”,忽略常数因子也是错的。涉及暴力枚举算法的时候,先算状态总数;涉及剪枝算法的时候,想清楚剪掉的是哪部分无效状态。这两个词常出现在综合题的题干里,期中不要求实现,但要求你判断复杂度级别。
3.2 填空题:栈空栈满、队空队满与递归出口
填空题考的是精确记忆和边界条件。整理三个必须“背且理解”的边界:第一,顺序栈从 0 开始存时,栈空条件是 top==-1,栈满条件是 top==MaxSize-1,链栈基本不用判满;第二,循环队列判空是 front==rear,判满分两种写法,牺牲一个单元是 (rear+1)%MaxSize==front,设 size 字段是 size==MaxSize;第三,递归出口写在函数最前面,比如二叉树的递归遍历,空树直接 return,不能等进入左右子树之后再判。这些内容在答案文档里可能散落在不同题目中,建议自己抄到一张卡片上,做题前扫一眼。
填空还爱考双向链表插入的指针修改顺序:在 p 节点前插入 s 节点,先动 s 的 prior 和 next,再动前驱的 next,最后动 p 的 prior,顺序不能反。很多同学先改 p 的 prior,导致前驱节点找不到了,后续操作全乱。顺序表相关的填空则集中在“平均移动次数”,删除第 i 个元素平均移动 (n-i) 个,大家习惯背公式,但考试时把 i 从 0 还是从 1 编号看仔细,这里差一个下标。
3.3 算法设计题:用“边界、主体、返回”三步模板写出高分答案
算法设计题是期中丢分最重的题型,也是答案文档最“不好抄”的部分,因为老师按要点给分。我总结的答题模板分三步:第一步,明确边界,包括空结构、单节点结构、非法参数的处理,这决定正确性;第二步,写主体,链表题用双指针,数组题用双端扫描,树题用递归,图题用队列或栈;第三步,确定返回,结果放在哪里、是否修改原结构、是否释放空间,这决定卷面完整性。
写伪代码时,先写注释式的逻辑轮廓,再补细节。判分老师通常看三件事:是否覆盖空列表、是否用对数据结构、时间复杂度是否与最优解同数量级。
| 题目类型 | 常用数据结构 | 核心步骤 | 易漏边界 |
|---|---|---|---|
| 链表类 | 双指针、头插法 | 逆置、合并、删除指定值 | 空表、尾节点、头节点链 |
| 树类 | 递归、栈 | 遍历、镜像、求深度 | 空树、单子树、递归出口 |
| 排序类 | 分治、堆 | 划分、合并、调整堆 | 循环边界 i 与 j 越界 |
| 图类 | 队列、栈、并查集 | BFS、DFS、拓扑序 | 已访问标记、重复入队 |
再给一个卷面习惯:先在草稿纸上写下“本题的时间复杂度要求、空间复杂度要求”,再动手。很多考场翻车不是因为不会,而是没看复杂度要求,写了一个正确但超时的解,丢一半分。算法大题不能当黑匣子处理,每一步最好写清“为什么这样做”。
提示:如果一道算法题你五分钟内没有给出结构思路,先放弃,做完其他题再回来看。期中考试时间紧,一道题卡死后面全崩。
3.4 画图与构造题:哈夫曼、最小生成树与散列过程的固定步骤
画图题不写代码,但必须在卷面上呈现过程。哈夫曼画图的步骤是:把所有权值排成升序,取两个最小的合并,新节点放回序列重新排序,画出合并树,边画边标权重。例如权值 2、3、5、7,先合并 2 和 3 得到 5,此时序列是 5、5、7,再合并两个 5 得到 10,最后 10 与 7 合并,WPL 是 22+32+52+71,结果唯一,但树形画法可能有左右互换的差异。
最小生成树题:Kruskal 按边权升序编号,逐条决定“加或不加”,用一个简单的集合标记判断是否成环,形成环就跳过;Prim 从起点出发画一个已选集合,每一步在集合边界找最小边。这两个过程只要写清楚“每一步加哪条边、为什么合法”,步骤分就拿到了。散列画图给出桶数组后,逐关键字写冲突探测路径,被占用的槽位画上标记,探测到空位再停。卷面上不要只画最终结果,中间探测次数很可能就是采分点。
4. 期中复习避坑指南:五类高频失分点与排查思路
我批过不少同学的期中试卷,也在找答案的路上踩过同样的坑。下面五类现象是高频失分点,每一条按“现象、原因、解决”来排查。
4.1 现象:答案看得懂,换道题就卡死
原因:只看答案的结论,没看答案的推导起点。链表逆置的代码看了能懂,题目变成“带头节点的循环链表逆置”,就卡住了。解决:把答案盖上,用自己的话把“为什么这么做”写成文字步骤;再做一道同类型变题验证。变题去哪找?作业题、老师 PPT、练习册的同章节题都可以。关键是做完之后对照答案核对思路,不是核对结果。
4.2 现象:复杂度结论记混,答错还觉得合理
原因:排序算法的时间复杂度是记忆型知识点,但选择题经常考“最坏和平均之间的差异原因”,只背结论容易失分。比如快排最坏情况 O(n^2),很多人知道结论,但不知道为什么——因为每次划分极端不均。解决:把复杂度按“比较次数”和“移动次数”分开记忆,归并用分治递推自己推导一遍,养成“写递推式再定性”的习惯。顺手把暴力枚举算法和优化算法放一起比,O(n^2) 和 O(nlogn) 的差距在数据规模变大后有多明显,心里有数。
4.3 现象:递归边界漏写或顺序错
原因:递归出口写在函数开头时没有检查空指针或空树,或者出口条件写反,导致栈溢出。解决:写递归第一行固定检查 null 或空容器;然后在纸上展开一次递归调用的执行过程,确认递归深度和出口。复习时专门找三道递归题定时训练:树深度、链表逆序输出、斐波那契变体。这三道能一次写对,递归边界基本没问题。
4.4 现象:图的遍历顺序与标准答案不一致
原因:邻接点的访问顺序没按题设条件排列。题设没说明时,默认按编号升序,但有些题目给的边表输入顺序就是访问顺序,没有默认这一说。解决:做题前先判断邻接表是否有序;给了边集就按边的存储顺序走。还有一个小细节——BFS 是“入队时标记”还是“出队时标记”?标准写法是入队时标记,否则同一个节点会被多次入队,序列就乱了。
4.5 现象:排序的稳定性与场景选择想当然
原因:看到“排序”两个字就直接默认冒泡或快排,没把题里的“稳定”“内存受限”“数据基本有序”当成约束条件。解决:把排序选择题的三个关键词提取出来——数据量、是否要求稳定、是否内存受限,然后按第 2.6 节的表比对:快排默认首选但最坏差,归并稳定但费内存,堆排省内存不稳定,插入排序适合基本有序。做题时先在题干划出这些关键词,再选答案。
5. 考前 7 天怎么用这份练习题:限时模拟、错题闭环与讲题验证
考前一周的用法,我给一个按天拆的模板:
| 天次 | 白天的任务 | 晚间任务 |
|---|---|---|
| 第 1 天 | 浏览练习答案的目录,统计各模块题数与权重,划出老师偏爱的模块 | 补 2.1、2.2 的知识点与公式卡片 |
| 第 2 天 | 专项:线性表、栈、队列,做完对应练习题并对照答案 | 整理错题到卡片 |
| 第 3 天 | 专项:树与二叉树,做遍历还原、哈夫曼,写两道递归题 | 重做昨天错题 |
| 第 4 天 | 专项:图,手算 Dijkstra,画最小生成树 | 复习错题卡片 |
| 第 5 天 | 专项:查找与排序,手算 ASL,默写复杂度表 | 综合错题 |
| 第 6 天 | 综合模拟:限时 60 分钟完成一份模拟卷 | 对答案,统计失分模块 |
| 第 7 天 | 只看错题与公式卡片,不做新题 | 傍晚快速重画一遍易错图 |
验证方法我习惯用三件套。第一是讲题法:扣上答案,把每道错题讲给同学或自己听,讲不清楚的地方就是没搞懂的地方,重点回看。这方法看起来很朴素,实际效果比重复刷题好,因为讲解强迫你组织逻辑。第二是限时模拟:考试是限时系统,平时练习如果不限时,考场上节奏必然崩。至少完整模拟一次,按分值分配时间,一道二十分的大题最多给十二分钟。第三是错题三遍法:第一天做错,第二天重做,第四天再看一遍,还错的地方做标记,考前最后一天只看标记处。错题的价值大于一切新题。
最后说一句我自己的血泪经验:大一期中前,我把练习册答案从头到尾背了一遍,成绩出来之后,唯一有把握的大题是“没有创新问法的原题”,但那种题的占比从来不超过三成。从那以后我复习任何一门课,都先盖答案再写过程。这份 doc 你下载到了,说明你已经有了别人没有的资源,但资源只有变成你自己的推导过程才有意义。希望这篇复习路径能帮到你,也祝你把那 60 分钟的卷子写满、写对。
本文还有配套的精品资源,点击获取