资讯详情

严蔚敏数据结构习题集答案怎么用:解决编译报错并改写为可运行代码

📅 2026/9/25 12:07:08 | 华诺云谱 👁 阅读
严蔚敏数据结构习题集答案怎么用:解决编译报错并改写为可运行代码
简介严蔚敏《数据结构C语言版习题集》全答案是一份面向计算机专业学生、考研备考者及自学者的经典配套资料覆盖绪论、线性表、栈与队列、串、树、图、查找与排序等核心章节针对每道习题给出可直接运行的C语言实现及关键注释。资源包共1个文件类型为PDF大小431KB内容编排紧凑支持目录跳转方便按章节检索与对照学习。该资料已有10399人学习下载广受同类课程学习者认可。答案中不仅包含标准代码还结合冒泡排序、斐波那契序列动态规划求解、结构体与枚举类型的数据组织、霍纳法则多项式求值等典型实例并附有复杂度分析或算法注解有助于理解不同数据结构的适用场景与设计思路。对于正在啃教材、刷习题的读者而言这份全答案能够显著降低卡壳概率既可用来自我检验也可作为教师备课的参考素材。1. 严蔚敏《数据结构C语言版习题集》全答案为什么别人能刷完你连编译都过不了很多人下载这份 PDF 后第一件事是打开目录对着课后题抄。抄到栈和队列那一章代码粘进编译器弹出一屏报错于是给这份答案判了“质量不行”。实际恰好相反严蔚敏《数据结构C语言版习题集》的答案几乎每道算法题都给了完整 C 语言实现只是它保留着二十多年前的代码习惯——默认你有配套公共头文件、默认用 C 编译器编译、默认你清楚 Status 和 ElemType 是什么。期末复习、考研冲刺、408 数据结构需要手写代码的场景里这份答案依然是对照算法思路最完整的参考资料。问题从来不是答案对不对而是你怎么把它跑起来、改造成能在考卷或 IDE 里立住的代码。下面把整个过程拆开讲。2. 先弄懂这本题集的语言版本严蔚敏版 C 的三种奇怪写法2.1 章节怎么对上从习题集目录到考研/期末考点严蔚敏《数据结构C语言版习题集》按教材章节出题常规版本覆盖绪论与算法分析、线性表、栈和队列、串、数组和广义表、树和二叉树、图、查找、内部排序部分印次还包含动态存储管理和外部排序。王道 408 和期末复习的考点几乎全落在这几张表里所以先别急着逐题刷拿一张纸把习题集目录和你的考纲对齐。考研一般砍掉广义表和动态存储管理重点压在树、图、查找、排序四个大块期末考则以线性表、栈队列、二叉树为主。我按高频考点做了一个对照方便你筛题习题集章节高频考点复习优先级第 1 章 绪论时间复杂度、算法设计题低但常考分析第 2 章 线性表顺序表、单链表插入删除、双链表高第 3 章 栈和队列栈的应用、循环队列判满高第 4 章 串KMP 的 next 数组中第 5 章 数组和广义表矩阵压缩、稀疏矩阵低第 6 章 树和二叉树三种遍历、线索化、Huffman 树高第 7 章 图邻接表/邻接矩阵、DFS、BFS、最小生成树高第 9 章 查找折半查找、BST、哈希高第 10 章 排序快排、堆排、归并排序高这张表还有一个用途决定 PDF 里哪些答案值得逐字看、哪些扫一眼思路就行。比如考研大纲不考广义表那第 5 章后半部分的答案可以直接跳过省下的时间能多刷两道二叉树。2.2 Status 和 ElemType答案里到处都是的“非标准类型”打开任意一道算法题答案第一行大概率是Status或void。Status 不是 C 标准库里的类型是严蔚敏教材约定俗成的“函数执行状态返回值”取值包括 OK、ERROR、OVERFLOW、INFEASIBLE 这些宏。ElemType 则是“元素类型”的占位符表示链表、栈、队列里存的数据类型。这意味着你不能把 PDF 里的代码原样粘进一个空文件就编译。代码背后缺一套公共定义。我一般会在工程里放一个 common.h一次性补全这些约定/* common.h —— 替代严蔚敏配套的 c1.h 公共头文件 */ #include stdio.h #include stdlib.h #define TRUE 1 #define FALSE 0 #define OK 1 #define ERROR 0 #define INFEASIBLE -1 #define OVERFLOW -2 typedef int Status; /* 函数返回状态OK/ERROR/OVERFLOW 都映射到 int */ typedef int ElemType; /* 元素类型按习题要求改成 char 或结构体 */逻辑说明严蔚敏教材配套源码里有一个 c1.h里面就是这批宏和类型别名。网上流传的习题集答案 PDF 大多默认你已经 include 过它所以单独粘题解代码时才会各种报错。我习惯新开工程时先把 c1.h 里那套公共定义重建出来之后所有.c文件都#include common.h省得每道题重定义一遍。参数说明ElemType是全局开关。习题里元素是整数时保留typedef int ElemType题目改成字符串时把这一行换成typedef char ElemType如果是学生表、图书表这类结构化数据就定义成结构体别名。一个文件里尽量只保留一份类型别名避免在多个 .c 文件里重复 typedef 导致冲突。2.3 函数参数里的这是 C 语法别用 gcc 硬编严蔚敏这本书的不少答案沿用了教材配套源码的习惯大量使用引用参数。最典型的是链表题里的ListInsert(LinkList L, int i, ElemType e)。在形参里不是取地址而是 C 的引用含义是“直接操作实参本身不需要用指针”。ANSI C 没有这个东西。所以常见做法有两个第一把包含这类代码的文件后缀改成.cpp用 g 或 Dev-C 编译第二把引用全部改写成指针。我强烈建议考研党用第二种因为 408 手写代码时你写在答题卡上的必须是 C 语言能接受的写法不能带引用。/* C 语言写法把引用参数 LNode *L 改成 LNode **L */ void ListInsert(LNode **L, int i, ElemType e) { LNode *p *L; int j 0; while (p j i - 1) { /* 指针移动到第 i-1 个结点 */ p p-next; j; } if (!p || j ! i - 1) return ERROR; /* i 越界 */ LNode *s (LNode *)malloc(sizeof(LNode)); if (!s) return OVERFLOW; s-data e; s-next p-next; p-next s; return OK; }逻辑说明二级指针LNode **L保存的是头指针变量的地址函数内*L才能拿到真正的链表头指针。在插入、创建链表这类“可能改动头指针本身”的操作里二级指针是最稳的写法。参数说明调用处变成ListInsert(list, 1, e)也就是把原来list这个头指针变量的地址传进去这样函数里给*L赋新值时外面list才跟着变。再补一张改写对照表遇到 PDF 代码直接查原 C 写法C 语言等价写法void f(LNode *L)void f(LNode **L)调用f(L)调用f(L)p new LNodep (LNode *)malloc(sizeof(LNode))delete pfree(p)需要提醒的是new/delete 和 malloc/free 不止是换名字那么简单new 会调用构造函数malloc 只是分配裸内存所以在处理字符串结构体这类带资源的数据时用 malloc 分配后要记得手动初始化字段这是从抄答案到自己写最容易忽略的一步。2.4 习题答案依赖的“头文件套娃”一个工程怎么组织文件严蔚敏教材有一整套配套头文件c1.h 放公共常量c2-1.h 放线性表结构定义c6-1.h 放二叉树结构定义题解代码顶层文件靠#include把它们串起来。习题集 PDF 里有些答案直接贴的是这种“多文件工程”里的题解片段单看某一页你会以为缺了半个文件。我一般按这个结构组织本地工程ds_answers/ ├── common.h # 公共常量、Status、ElemType ├── linklist.h # 线性表结构和函数声明 ├── linklist.c # 线性表函数实现 ├── ex2_insert.c # 某道习题的测试入口 └── makefile # 可选多文件编译用每个 ex*.c 文件只包含两三样东西#include common.h、#include linklist.h、一个 main 函数。这样 PDF 里的算法实现整体放进 .c 或 .h测试入口单独写。参数说明在 Dev-C 或 VS Code 里直接把所有 .c 文件加入编译即可如果只用命令行gcc linklist.c ex2_insert.c -o ex2_insert。这样组织还有一个好处同一份 linklist.c 可以在多道题之间复用改的只是 main 里的测试用例。3. 把 PDF 里的一段答案变成本地能跑的代码最小复现步骤3.1 准备环境VS Code 配置 C 语言环境够用这一步不用折腾复杂 IDE。先装一个 GCC 工具链常见做法是装 MinGW-w64然后把 bin 目录加进 PATH。VS Code 里装 C/C 扩展新建.vscode/tasks.json配置编译任务。Dev-C 也能跑严蔚敏的题因为它的编译器本来就是 g天然兼容引用语法缺点是报错信息不如 VS Code 直观。如果你只想快速验证某一道题不用配完整工程。把答案代码和 common.h 放同一个目录终端里按下面的命令编译即可。我见过有人花一下午配置 IDE最后发现其实只需要一条 gcc 命令这个时间拿来刷三道链表题更划算。3.2 从 PDF 抽一道单链表插入题完整代码长这样我拿第 2 章线性表里最常考的“带头结点的单链表在第 i 个位置插入元素 e”举例。PDF 里的答案默认你已有结构体定义和公共头文件我把它整理成一份能直接编译的完整文件/* ex2_insert.c —— 带头结点单链表第 i 位插入整体可编译 */ #include stdio.h #include stdlib.h #include common.h typedef struct LNode { ElemType data; struct LNode *next; } LNode, *LinkList; /* 初始化带头结点的空链表 */ Status InitList(LinkList *L) { *L (LNode *)malloc(sizeof(LNode)); if (!*L) return OVERFLOW; (*L)-next NULL; return OK; } /* 在第 i 个位置插入元素 ei 从 1 开始 */ Status ListInsert(LinkList L, int i, ElemType e) { LNode *p L; int j 0; while (p j i - 1) { /* 指针移动到第 i-1 个结点 */ p p-next; j; } if (!p || j ! i - 1) return ERROR; /* i 不合法 */ LNode *s (LNode *)malloc(sizeof(LNode)); if (!s) return OVERFLOW; s-data e; s-next p-next; p-next s; return OK; } void PrintList(LinkList L) { LNode *p L-next; while (p) { printf(%d , p-data); p p-next; } printf(\n); } int main() { LinkList L; InitList(L); ListInsert(L, 1, 10); ListInsert(L, 2, 20); ListInsert(L, 2, 15); /* 插到中间 */ PrintList(L); /* 预期输出10 15 20 */ return 0; }逻辑说明InitList 用二级指针LinkList *L因为要修改调用方的头指针变量ListInsert 只遍历链表不改变头指针所以用一级指针LinkList L。main 里的三次插入分别验证头插、尾插、中间插入三种情况。这里为什么强调带头结点因为带头结点后空表的判断从L NULL变成L-next NULL插入逻辑可以统一不需要单独处理“插在第一个”的特殊分支。这是严蔚敏书里反复出现的套路也是面试手写链表时最常见的考察点。参数说明插入位置 i 从 1 开始和数组下标从 0 开始不一样判断j ! i - 1用来排除 i 太大或太小的情况。malloc 成功后没有手动释放因为这是单次运行的验证程序操作系统会回收但如果是长跑的服务程序free就必不可少。3.3 编译运行一条命令完成验证把上面的 ex2_insert.c 和 common.h 放在同一目录后命令行执行gcc ex2_insert.c -o ex2_insert ./ex2_insert第一个命令把源文件编译成可执行文件-o指定输出文件名第二个命令运行。预期输出是10 15 20。如果你想确认边界行为把 main 里的ListInsert(L, 0, 1)取消注释再跑一次应该返回 ERROR 且链表不变。这是对“参数不合法”分支的验证比只看正常输出更有说服力。如果编译报undefined reference to WinMain通常是 main 函数写错了名字或文件里多了一个入口如果报LNode undeclared则是结构体定义没被包含进来检查 common.h 路径和 include 顺序。等到运行结果和 PDF 里的输出不一样时先别急着怀疑答案——检查一下是不是printf的格式串和答案用的分隔符不同很多人在这里对不上答案其实是输出格式的问题。4. 从抄答案到真正会做题公共头文件定制、递归改非递归与三个必调参数4.1 ElemType 的定制一份代码同时应付整型、字符串和结构体前文说过ElemType 是全局开关。真正动手时会发现定制的粒度决定了你能不能在多个习题之间复用代码。我一般定义三套预置方案/* ElemType 三种常用定制 */ typedef int ElemType; /* 整型元素 */ typedef char ElemType[20]; /* 定长字符串元素 */ typedef struct { int id; char name[20]; } Student; typedef Student *ElemType; /* 结构体指针元素 */这里有一个坑typedef char ElemType[20]会让函数的形参写法变得别扭比如 ListInsert 的参数ElemType e实际是char e[20]传参时数组会退化成指针。我的做法是结构体题优先用指针方案typedef Student *ElemType;这样所有函数形参不用改代价是插入时要先 malloc 一块 Student 内存。刷题群里经常有人问为什么运行时报段错误八成就是这里只分配了指针没分配结构体空间。4.2 把递归遍历改成非递归考场上更稳的写法严蔚敏习题里的二叉树遍历答案大量使用递归代码确实短。但考研笔试和复试上机场景里递归有两个问题一是树很深时栈可能溢出二是某些判题环境对递归调用有限制。所以把递归改成显式栈是值得练的基本功。以中序遍历为例递归版本三行非递归版本用数组模拟栈/* inorder_iter.c —— 二叉树中序非递归遍历栈用数组模拟 */ #include stdio.h #include stdlib.h typedef char TElemType; typedef struct BiTNode { TElemType data; struct BiTNode *lchild, *rchild; } BiTNode, *BiTree; void InOrder(BiTree T) { BiTree stack[100]; /* 模拟栈应付常见习题足够 */ int top -1; BiTree p T; while (p ! NULL || top ! -1) { while (p ! NULL) { /* 左子树一路压栈 */ stack[top] p; p p-lchild; } if (top ! -1) { p stack[top--]; /* 出栈访问 */ printf(%c , p-data); p p-rchild; /* 转向右子树 */ } } printf(\n); }逻辑说明整个外循环条件是“当前结点非空或栈非空”反复执行“把左链压栈、出栈访问、转右子树”这三步。栈的大小 100 在常见习题里足够如果题目明确给了结点数上限 n改成stack[n]更严谨。参数说明TElemType 是二叉树结点数据类型的占位符这里按字符处理如果数据是 int把typedef char TElemType改成typedef int TElemTypeprintf 相应改成%d。如果你想练先序和后序的非递归版先序只需把访问时机提前到入栈之前后序则需要给栈元素加一个标记位表示右子树是否已访问。这道题在“王道 408 数据结构代码必背”清单里几乎是固定考点建议练到能默写。4.3 三个必调参数容量、初始值、溢出判断刷这份答案时有一类 bug 和算法本身无关只是参数没调好。我总结出三个最常调整的地方参数常见默认值什么时候要改栈/队列数组容量100处理 n100 的输入时改成题目给定上限InitList 的初始状态L-next NULL带头结点/不带头结点会改变判断条件哈希表表长13除数取模时表长选质数冲突更少比如循环队列判满答案里常见的写法是(rear 1) % MAXQSIZE front这意味着队列最多存 MAXQSIZE-1 个元素。如果你把 MAXQSIZE 改成 10实际只能存 9 个这就是“容量少一个”的坑。这个写法本身不是错误而是牺牲一个空间换“空/满可区分”的经典做法设参数的人心里要有数。再比如顺序表插入答案里经常看到if (L-length MAXSIZE) return ERROR;这个判断。很多人只记得写插入逻辑忘了在插入前检查容量结果数据一多就把邻接内存写坏了。这三个参数是玄学吗不是它们只是把严蔚敏在代码里默认的那些约束重新摆到明处。先把它们填对再谈优化算法。5. 避坑用这份答案刷严蔚敏习题最容易翻车的 5 个地方这份答案 PDF 的题目和题号是跟着严蔚敏原教材走的所以踩坑一般不在题目本身而在把题解变成能运行的代码这条路上。下面 5 个问题是我见过最高频的翻车场景分布在编译、运行和资料源三个环节。5.1 编译层报错和答案本身没关系现象下载了某份“严蔚敏数据结构c语言版pdf”习题答案把单个题解复制到新建的 .c 文件里gcc 一编译就是二十多行报错集中在两类一类是expected ; before token另一类是Status undeclared。原因前者是题解里用了 C 的引用参数却用 gcc 按 C 语言编译后者是 PDF 里的代码默认你已经 include 过配套的公共头文件而你的工程里根本没有。两个都是“环境没接上”不是答案错。解决先写一个 common.h 补齐 Status、ElemType 和 OK/ERROR 宏再把用引用的函数按 2.3 的对照表改成二级指针或者干脆把文件后缀改成 .cpp 用 g 编译。两步做完编译层九成问题消失。我个人的习惯是在 Dev-C 里建工程最省事因为它默认就是 g引用语法直接吞下。5.2 运行层崩溃和对不上答案先查这三个地方现象一编译通过一运行就崩溃。原因链表、栈这些结构在第一次使用前没有初始化最常见的是LinkList L;声明完就直接 ListInsertL 还是野指针。解决在 main 开头先InitList(L)并且确认 InitList 里 malloc 之后把(*L)-next NULL写了。检查顺序永远是“先初始化再使用最后释放”。现象二快速排序跑完最终序列是对的但中间某几趟的输出和答案不一致。原因快排的每一趟结果依赖枢轴选取方式严蔚敏教材是取第一个元素从两端交替扫描习题集答案或你自己的改写版可能用了三数取中或者先跟最后一个元素交换再 partition。解决对答案前先确认它给的是“最终有序序列”还是“每趟排序后的序列”。如果是每趟结果把你的枢轴选取改成和它一致如果只看最终序列用自己最熟练的写法就行。数据结构排序算法这一章的习题最容易栽在这个差异上。现象三删除链表结点后程序偶尔崩溃或者打印出野值。原因先 free(p) 再读 p-next读了悬垂指针或者删的是头结点但外面的头指针没更新。解决删除前先q p-next; p-next q-next; free(q);也就是先完成链表接线再释放内存。删头结点的情况函数参数要用二级指针LinkList *L把新头传出去。悬垂指针是 C 语言内存管理里最经典的坑408 代码题也爱考值得反复练。5.3 资料层PDF 源文件本身要先筛一遍现象从 PDF 复制题解代码粘贴进 IDE 后光标指着某个括号报错找了半天发现那是个全角括号或者分号是全角分号有时代码里还混着水印字符。原因网上流传的“严蔚敏数据结构c语言版pdf”答案很多来自扫描件 OCR字符识别出现偏差很正常全角符号、空格丢失、题号错位比比皆是。有些版本前几页正常后面章节开始缺图少字。解决优先找文字版 PDF复制后先在编辑器里开启“显示空白字符”把全角符号批量替换成半角。如果 PDF 质量太差我的习惯是只看它的思路然后合上 PDF 自己把代码敲一遍——这个流程顺带把题也练了比对着乱码改半天下班强得多。这是踩出来的血泪经验。还有第五种隐藏的坑你手上的教材印次和习题集印次不一致导致个别题号错位。对不上答案时先看题号编号规则别急着改代码。6. 把答案册变成你自己的刷题笔记三组输入验证法我刷这份习题集的习惯是每道代码题不只看答案对不对而是准备三组输入去验证。第一组是题目自带的样例跑通是最低要求第二组是边界输入比如空表、单结点、满树、i1 或 in 的插入第三组是故意设计的非法输入比如插入位置 0、负数、超过表长看程序会不会优雅地返回 ERROR 而不是崩溃。我给每一道难题单独建一个验证目录里面只放两个文件一个main.c放三组测试用例一个algo.c放算法实现。结构类似这样/* main.c —— 三组输入验证骨架 */ void test_normal(void) { /* 题目自带的样例 */ } void test_boundary(void) { /* 空表/空树/单结点/满容量 */ } void test_invalid(void) { /* 非法位置/超长输入/空指针 */ }三组跑下来这道题才算真正过手。原因很简单考研和复试上机题最喜欢在边界条件上埋伏笔而 PDF 答案往往只演示了正常路径。比如循环队列判满、二叉树空树遍历、哈希冲突链过长这些场景只有在第二、第三组输入里才会暴露。复习到第二轮时我会再回来跑一遍哪个文件跑不顺就重点补哪个比从头翻 PDF 快得多。说句实在话严蔚敏这书的代码风格偏老但这本答案册依然是目前最完整的 C 语言数据结构题解参照物。与其到处找新的总结笔记不如沉下心把它的题解读透再把代码改写成自己能默写的版本。我到今天写链表题仍然习惯先写p L再往后走这个肌肉记忆就是从这份答案里一遍遍敲出来的。希望帮到你。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑