简介:一套围绕PTA“数据结构与算法”题目集整理的编程题解合集,适合正在备考PTA、学习数据结构课程或需要刷题参考的高校学生与自学者。压缩包共41个文件,其中38份cpp源码为可运行解法,覆盖图论、排序、树、字符串匹配等高频考点;2个h头文件定义了图与队列的链式存储结构,辅助理解底层实现;另有1份md说明文档梳理题目与思路,整包仅38KB,便于快速下载与查阅。资源目前已吸引3000余人学习,内容涉及迪杰斯特拉、弗洛伊德、普里姆、克鲁斯卡尔、拓扑排序、KMP、AVL树、哈夫曼编码以及最大子列和、是否同一棵二叉搜索树、插入或归并等经典题目,可帮助读者对照题解理解算法思路、动手复现并查漏补缺。无论是日常练习、期末复习还是考前冲刺,这份紧凑的资料集都值得收藏。
1. 拿到“PTA-数据结构与算法题目集.zip”之后,先别把它当成一个普通压缩包
“PTA-数据结构与算法题目集.zip”并不是一份源码工程,而是一个围绕“数据结构与算法”课程体系整理出来的完整练习仓库:里面有按专题分好的题目、样例输入输出、参考代码片段和说明文档。它的价值在于,你把题目从在线评测平台搬到本地之后,可以离线阅读题面、反复改代码、自己造数据验证,而不需要每次都被平台的编译队列和提交格式限制住。适合正在上数据结构课的学生、准备求职算法笔试的开发者,以及想系统补一遍基础算法的从业者。很多人在这个压缩包上翻车,不是题目难,而是文件结构没看懂、本地跑通后提交却全错。这篇笔记会把解压、建环境、刷题、避坑的完整路径讲清楚。
2. 解压后先别急着做题:这份题目集里到底装了什么
拿到压缩包,最常见的动作是双击解压然后随手点开一个文件,发现内容和自己想象的不一样。先花十分钟把目录结构摸清楚,后面能省下大量时间。
2.1 先看目录树:分清题面、样例、模板三块内容
解压之后,我建议先用一条命令把整体结构打出来,不要凭文件名猜测。Windows 下用资源管理器也可以,但命令行输出更利于建立索引。
unzip -l PTA-数据结构与算法题目集.zip | head -80这条命令只列压缩包内容,不实际解压。-l参数的意思是 list,只做清单输出;head -80限制只显示前 80 行,避免一次刷屏。如果已经解压到本地,就直接进目录看:
cd PTA-数据结构与算法题目集 find . -maxdepth 2 -type d | sort常见的目录组织方式是按专题分文件夹,比如“线性表”“栈与队列”“树”“图”“排序”“哈希”等,每个专题下面再放若干道题。也有的版本会把题面统一放在problems目录,样例放在samples目录,模板代码放在templates目录。用find只看两层目录,是为了先抓住大类,不要一头扎进某个子目录里出不来。
这里要提醒一句:压缩包内部的目录结构在不同来源的版本里差别很大。有的按题号排,有的按知识点排,还有的直接平铺几百个文件。所以第一步不是打开某道题,而是建立你自己的索引表。用下面这个 Python 脚本把每个目录下的文件数量和类型统计出来:
import os from collections import Counter root = "PTA-数据结构与算法题目集" for dirpath, dirnames, filenames in os.walk(root): exts = Counter(os.path.splitext(f)[1].lower() for f in filenames) if filenames: print(f"{dirpath}: {len(filenames)} 个文件, {dict(exts)}")这段脚本会遍历所有子目录,统计每个文件夹里的文件个数和扩展名分布。.c、.cpp、.py是代码,.md、.txt是题面,.in和.out是样例输入输出。看到某个目录只有.in没有.out,说明样例输出可能内嵌在题面文档里,别到处乱找。
2.2 四类核心素材:题面、样例、模板与数据构造器
把这四类素材区分清楚,后续刷题才不会拿错东西。
第一类是题面文档。多数是.md或.txt格式,描述题目背景、输入输出格式、数据范围和时间限制。注意有些题面里写的时间限制是伪限制,像“1秒”这种,在本地机器上跑 0.5 秒不代表平台能过,这个后面细说。
第二类是样例输入输出。通常一个样例是三件套:.in输入文件、.out输出文件、以及题面里直接贴的文本版样例。这三者偶尔会不一致,以.in/.out文件为准。如果发现文件缺失,直接从题面里复制文本自己建文件。
第三类是参考模板代码。有些题目会附一个带注释的框架,比如链表的创建、二叉树的递归遍历。这部分代码往往是为了降低入门门槛写的,不一定是性能最优解。照抄能过样例,但碰上大数据会超时,需要理解后自己重写。
第四类是数据构造器。版本较完整的题集里会带gen.py或random_input.py,用来生成随机的测试数据。如果你最后要验证算法的时间复杂度,这类脚本是必需品。
用一个表格总结一下:
| 素材类型 | 常见扩展名 | 用途 | 拿错的表现 |
|---|---|---|---|
| 题面 | .md / .txt | 描述题意与格式 | 不看题面直接写代码 |
| 样例输入 | .in | 程序输入 | 把输出文件当输入 |
| 样例输出 | .out | 比对依据 | 本地全对,平台上全错 |
| 模板代码 | .c / .cpp / .py | 快速上手 | 直接提交导致超时 |
| 数据构造器 | .py / .sh | 造大批量数据 | 没有压测直接交 |
这个表不算什么高深技术,但很多人在“本地全对,平台全错”的时候,回头查才发现自己把.out文件当成基准输入了。先理清素材类型,就能避开第一类低级错误。
3. 本地做题为先:一套能直接抄的编译与运行模板
把目录结构摸清之后,下一步是在本地把一道题从读入到输出完整跑通。这里给出一套我常用的最小工作流,不依赖任何 IDE,只用命令行,保证你在任何机器上都能复现。
3.1 用 C 最小模板把第一题跑通:scanf 循环与输出重定向
数据结构与算法题集的经典场景是“多组输入,直到 EOF”。很多初学者只处理一组输入,提交之后发现后面的测试点全部超时或答案错误。先看一个最干净的 C 骨架:
#include <stdio.h> int main(void) { int n; while (scanf("%d", &n) != EOF) { // 每一组输入做一次处理,然后立即输出 printf("%d\n", n * 2); } return 0; }重点在于while (scanf(...) != EOF)。scanf的返回值是成功匹配的参数个数;没读到任何数据时返回EOF。用这个循环,输入有多少组就处理多少组,不需要预先知道数量。这是在线评测平台的通用输入约定,几乎所有题目都适用。
如果题目第一行给一个T表示后面有 T 组数据,模板就改成:
#include <stdio.h> int main(void) { int T, n; scanf("%d", &T); while (T--) { scanf("%d", &n); printf("%d\n", n * 2); } return 0; }while (T--)的意思是先判断T是否为非零,再自减,循环恰好执行 T 次。这里不需要额外的计数器变量,代码更紧凑。编译时我推荐带上这些参数:
gcc -O2 -std=c11 -Wall answer.c -o answer-O2开优化,让运行时间和平台更接近;-std=c11固定语言标准,避免某些平台默认老标准导致的编译差异;-Wall打开警告,很多隐藏问题在警告里就能看出苗头。如果你的环境是 Windows 且没装 gcc,建议装一个通用的编译工具链,或者用 WSL,不要在 IDE 里点运行了事,因为 IDE 的“运行”往往不经过标准输入重定向。
3.2 写一个批量比对脚本:把手工贴样例变成一条命令
题集里的样例文件通常长这样:01.in和01.out成对出现。手工把输入粘贴进去、再把输出和答案对比,效率太低。写一个 bash 脚本,一次跑完所有样例:
#!/bin/bash # run_all.sh —— 编译并运行所有样例 gcc -O2 -std=c11 -Wall answer.c -o answer || exit 1 for in_file in *.in; do base="${in_file%.in}" if [ -f "${base}.out" ]; then ./answer < "$in_file" > "${base}.res" if diff -u "${base}.out" "${base}.res" > "${base}.diff"; then echo "PASS: $base" else echo "FAIL: $base, 看 ${base}.diff" fi fi done脚本逻辑是:编译失败直接退出;遍历当前目录所有.in文件;有对应.out时运行程序,把结果写到.res;diff -u逐行对比,有差异就把差异存到.diff文件。diff不加参数直接看退出码也行,但存成.diff文件方便反复查看。
这里有个参数细节:base="${in_file%.in}"是 bash 的字符串截取,意思是去掉文件名的.in后缀。如果输入文件叫01.in,base就是01,对应的输出和结果文件分别是01.out、01.res。如果你在 Windows 上用的是 cmd 而不是 bash,就把同样的逻辑写成批处理:
@echo off for %%f in (*.in) do ( answer.exe < %%f > %%~nf.res fc %%~nf.out %%~nf.res )%%~nf在 cmd 里表示取文件名去掉扩展名的部分,作用与 bash 的${in_file%.in}一致。注意批处理里 for 变量用双百分号,这是新手最容易卡住的地方。
3.3 Python 解法的输入输出细节:别在换行上翻车
题集里不少同学用 Python 刷。Python 写算法题有个经典坑:用input()读多组数据时,遇到空行会直接报EOFError,或者因为strip()处理不当导致输出格式不一致。我建议统一用下面这个模板:
import sys def main(): data = sys.stdin.read().split() if not data: return n = int(data[0]) print(n * 2) if __name__ == "__main__": main()sys.stdin.read()一次把整个标准输入读成字符串,.split()按空白字符切分,天然忽略换行、空格和行尾的空行。这样处理多组数据时,只需要按顺序取data里的元素,不需要关心行结构。代价是数据量极大时内存占用偏高,但题目集里的数据规模通常不至于撑爆内存。
注意if __name__ == "__main__":这行不是装饰,它保证你这个文件被直接运行时才执行main();如果被别的模块导入,不会自动跑逻辑。这在写数据构造器或者多文件协作时很重要。
输出格式上,Python 的print自带换行,所以每行结果天然符合“一行一个答案”的约定。如果你用的是sys.stdout.write,记得手动补\n,这是另一个高频翻车点。
4. 踩坑记录:本地下得了场、平台过不去的 5 个高频问题
这部分是血泪经验。题集本地跑通不算本事,能稳定提交才是目的。下面这些问题我见过大量同学反复踩,每一条都是“现象 → 原因 → 解决”的结构。
4.1 本地能过,平台全错:输出格式的隐形差异
现象:本地样例全 PASS,代码原封不动提交到在线评测平台,结果是答案错误,而且错的是好几个测试点,不是全部。
原因:最常见的是输出格式多了一个空格或少了一个换行。在线评测平台做的是逐字符比对,printf("%d\n", x)和printf("%d ", x)在视觉上一样,但机器判定完全不同。另一种常见情况是程序把调试用的printf也提交上去了,平台把那行多余输出当成答案的一部分。
解决:提交之前,先确认题面里“输出格式”那一段的措辞:每行一个结果还是空格分隔,结尾是否允许额外空行。检查一遍代码里除了最终答案之外没有任何printf输出。本地比对脚本里的diff是严格模式,如果本地都过了,那重点检查是不是提交错了文件——很多同学本地改的是answer.c,提交的却是平台上的旧代码。
4.2 scanf 与 getchar 混用导致读入错位
现象:题目要求先读一个整数,再读一行字符串。代码里先scanf("%d", &n),然后gets(s)或者getchar(),结果字符串的第一个字符是空行,后面所有字符都错位。
原因:scanf("%d", &n)读走数字后,输入缓冲区里还留着那个换行符。gets或getchar会先把这个换行符读走,导致真正的字符串内容整体前移。
解决:在scanf之后用一个getchar()主动吞掉残留的换行符,或者更干脆,全部用scanf的格式串控制空白:
scanf("%d", &n); getchar(); // 吞掉 n 后面的换行符 fgets(s, sizeof(s), stdin);fgets会连换行一起读进字符串,如果需要去掉末尾换行,再手动把s[strcspn(s, "\n")]置为'\0'。不要用gets,它在 C11 标准里已经被移除,很多平台编译直接报错。记住一个原则:混用格式化输入与行输入时,换行符一定是你的敌人。
4.3 段错误查不出位置:编译期开调试信息
现象:本地运行样例没问题,构造一个稍大的数据后程序直接崩溃,终端只提示Segmentation fault,不告诉你哪一行。
原因:数组越界、空指针访问、超大递归栈。题目集里常见的链表题、树题最容易在空指针上翻车。样例数据通常很小,空指针没触发;压测数据一大,问题立刻暴露。
解决:编译时加上-g参数,用调试器直接定位:
gcc -g -O0 answer.c -o answer_debug gdb ./answer_debug run < big.in bt-g生成调试符号,-O0关闭优化让代码顺序和源码一致;bt是 backtrace,打印崩溃时的调用栈,一眼就能看到是哪一行的什么操作导致的段错误。如果觉得 gdb 不熟,也可以先用printf打印关键位置,缩小范围后再上调试器。我一般会在链表节点创建和指针移动的地方各打印一行,快速二分定位。
4.4 全部测试点超时:先怀疑输入输出,再怀疑算法
现象:本地跑样例瞬间完成,提交平台显示所有超时(TLE)。有的同学立刻开始优化算法,结果折腾半天没效果。
原因:数据结构与算法题集里,超时最常见的原因是输入输出太慢。C 语言用了cin且没有关闭同步、Python 用了input()逐行读、或者算法里嵌了大量无用printf,都会造成数量级差异。另一个原因是题目没看清,把“多组输入”当成了“单组输入”,导致需要跑完全部数据的代码只处理了第一组,平台等待后续输出直到超时。
解决:C 语言保持用scanf/printf,如果非要用cin/cout,在main开头加:
ios::sync_with_stdio(false); cin.tie(0);Python 则换成上一章的sys.stdin.read()模板。如果确认输入输出没问题,再去做算法优化。这里有个实用技巧:把样例数据复制很多份拼成一个大输入文件,本地跑一下看耗时趋势;如果耗时和数据量成线性增长,大概率是输入输出开销,而不是算法复杂度问题。
4.5 文件名和题号对不上:提交的是旧版本
现象:改完代码保存,运行run_all.sh全 PASS,但提交到平台后代码还是旧行为。检查半天发现自己一直在改answer_v2.c,而提交上去的是answer.c。
原因:题目集文件多,很多人习惯复制一份新文件再改,结果没有清理旧文件。run_all.sh里写死了gcc answer.c,编译的永远是那个文件,而人工改的是另一个。
解决:建立严格的命名规则:每题一个独立目录,目录名就是题号,目录里只保留当前生效的源码文件。清理旧文件可以用:
rm -f answer_v2.c answer_v3.c answer_final.c我自己的习惯是目录里只放solution.c或solution.py,编译脚本统一针对这个文件名。这样永远不会出现“改了对的、提交了旧的”这种乌龙。如果你已经把题目集解压到了本地,建议按题号重命名目录,比如把“树与二叉树”目录下的文件统一改成tree_01.c、tree_02.c这样的格式,索引起来一目了然。
5. 把这套题集变成自己的成绩单:统计、计时与三遍刷法
题目集刷完一遍不是终点,如何量化自己的掌握程度才是关键。这一章给出三个进阶用法,把静态的题目集变成动态的学习档案。
5.1 用脚本统计每个专题的正确率
刷题最怕的是“做过就忘”。我建议每道题跑通过之后,手动记录一次结果,格式随意,然后定期用脚本统计。比如给每个专题的题解文件加一个头部注释,标记状态:
// status: PASS // time: 2026-05-12然后用脚本一次性统计全部专题的正确率。写个通用的 Python 脚本:
import re from pathlib import Path for dirpath in Path("PTA-数据结构与算法题目集").rglob("*"): if not dirpath.is_dir(): continue total = 0 passed = 0 for f in dirpath.glob("solution.*"): total += 1 text = f.read_text(errors="ignore") if re.search(r"status:\s*PASS", text): passed += 1 if total: print(f"{dirpath}: {passed}/{total} = {passed / total:.0%}")rglob("*")递归遍历所有目录,glob("solution.*")匹配每种语言的题解文件,正则找出status: PASS的记录。输出结果像一张成绩单,哪块薄弱一目了然。看到占比低于百分之六十的专题,就该回去重刷。
5.2 用计时给不同解法建档
同一道题往往有几种合法解法。题集里的模板代码可能是最直白的写法,但不一定是最优的。建一个“暴力版 vs 优化版”的对比档案很有价值:
for i in 1 2 3 4 5; do /usr/bin/time -f "%e s" ./solution_opt < big.in > /dev/null done/usr/bin/time输出的是真实秒数,%e是耗时格式;循环跑五次是为了取稳定值,避免第一次运行时缓存的影响。把不同版本的时间记在同一张表里,训练自己对复杂度的直觉——比如看到 O(n^2) 的写法在 n=10^5 时跑到 8 秒,下次就会自觉去写 O(n log n)。
5.3 三遍刷法的具体习惯
第一遍按专题顺序做,目标是“见到题知道考什么”;第二遍打乱顺序做,目标是“脱离章节提示,凭题目特征判断解法”;第三遍只做错题和超时题,目标是“把薄弱点补齐”。
我个人的习惯是,每道错题在笔记里留一行记录:题目编号、错因、改后的思路。错因尽量写具体,比如“没考虑图不连通”“递归层数太深导致栈溢出”,而不是笼统写“不会做”。这个记录越具体,回头复习越有效。
这套题目集的正确打开方式不是“刷完”,而是“刷到能给自己讲清楚”。如果你能对着一个空目录结构,不看任何题面,把每个专题的知识点、常见坑和解法框架列出来,这份 zip 才算真正吃透了。希望这篇笔记能帮你在刷题路上少走几步弯路。
本文还有配套的精品资源,点击获取