尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

哈工大《数据结构》44讲精学指南:线性表、树、图与排序全攻略

哈工大《数据结构》44讲精学指南:线性表、树、图与排序全攻略 数据结构这门课很多人的学习状态是上课听懂了例题能看懂一到自己写代码就卡住期末复习时觉得链表、树、图、查找、排序全都见过但拿起题目还是不知道先建什么结构、用哪类算法。这套哈尔滨工业大学的《数据结构》全44讲正好围绕线性表、树、图、查找与排序五块主干展开适合大学在校生同步学也适合考研复习和期末突击时快速过框架。我最近重新跟着过了一遍最大的感受是它不靠花哨演示胜在覆盖完整、节奏克制。下面按实际学习顺序拆解不列空目录只讲每一部分要怎么学、容易踩哪些坑。1. 44讲到底讲什么线性表、树、图、查找与排序的覆盖方式1.1 课程主线与常见知识点44讲听下来主线其实是经典教材的目录节奏。先讲数据结构和算法的基本概念比如时间复杂度、空间复杂度这是用来评价算法好不好的尺度。然后进入线性表顺序表和链表的实现栈和队列的衍生。再到树和二叉树重点处理遍历和线索化哈夫曼树。然后是图存储结构、遍历、最小生成树、最短路径、拓扑排序和关键路径。再是查找顺序查找、折半查找、分块查找、二叉排序树、平衡二叉树、B树、哈希表。最后是排序插入排序、交换排序、选择排序、归并排序、基数排序。这张课程表覆盖了计算机专业“数据结构”课程的核心范围。它并不是要求你把每个算法代码逐行背下来而是建立“数据结构 算法”的判断能力遇到问题能选出适合的结构能写出基本算法能分析时间和空间复杂度。现在不少考研和面试题目本质都在考这套判断力。我建议你把课程内容按下面这张表做一次映射方便后续复习定位课程章节核心内容考试/面试常考方向线性表顺序表、链表、栈、队列指针操作、边界条件、栈和队列应用树二叉树、遍历、线索二叉树、哈夫曼树递归遍历、重建二叉树、WPL计算图存储、DFS/BFS、最小生成树、最短路径手工模拟、算法步骤、visited标记查找折半查找、BST、AVL、B树、哈希查找长度、冲突处理、结构选择排序插入、交换、选择、归并、基数稳定性、复杂度、每轮排序结果这张表也说明了一件事数据结构不是靠一个概念单独撑起来的越往后越综合。树里的递归思想会延续到图图的最短路径依赖队列和栈查找和排序直接服务后面的算法题。如果你在前期把线性表和树学得潦草到图和排序阶段会越跟越吃力。1.2 哪些地方最容易学偏很多人学数据结构会把注意力放在“背”上背复杂度、背稳定性、背定义。但考试和面试真正考的往往是给你一组数据让你写出某个算法的手工模拟过程给你一个场景让你选择合适的存储结构。所以我会特别提醒不要跳过手工模拟。排序算法要能手动走一遍过程图的最短路径要能按算法步骤把 dist 和 path 表格更新出来哈希表要会算冲突次数哈夫曼树要会从一组权值里逐步合并。另外不能只看不写。数据结构课程的代码量不算大但每个都很典型。如果你只是把44讲视频全部看完代码一次都没跑过基本等于白学。后面我会给出一个比较稳的学习流程先把课程结构和环境说清楚。2. 开始之前做好三件事教材、编译环境和时间安排2.1 教材怎么选先对齐语言再谈版本先明确一件事数据结构这门课不同教材用的实现语言不一样。有 C 语言版、C 版、Java 版、Python 版。这套课程标明的是 C 语言路线所以如果你手里有严蔚敏的《数据结构C 语言版》配合度会比较高。网上能搜到很多标注为王卓、王道或其他机构的数据结构课件、PPT这些资料可以作为补充但我不建议第一遍就混着看。不同资料的章节顺序、术语和实现方式有差异。比如同样一个结构有的叫“二叉排序树”有的叫“二叉搜索树”或“二叉查找树”。你觉得内容讲偏了其实只是名字不同。建议第一遍跟着课程自己的节奏走把教材当字典。哪个知识点不明白再去翻对应章节找定义和证明。不要一开始就囤一堆电子书和课件学完前三章再决定是否需要额外资料。2.2 编译环境与调试工具数据结构不需要高配数据结构课程的代码不需要 GPU也不需要多大的显存和内存普通笔记本就够。真正的门槛是你能不能编译运行 C 代码以及会不会用调试器。你需要的是一个能编译 C 语言并支持单步调试的环境。Windows 下可以配置 VS Code MinGW也可以用其他你熟悉的 IDEmacOS 可以用 Xcode Command Line ToolsLinux 本身带 gcc命令行编译也行。不要追求编辑器看起来多先进关键是能断点、能看变量、能观察指针地址。这里多说一句调试器的重要。链表、二叉树这类指针操作如果只靠 printf 输出排查效率很低。单步断点能看到每个节点的地址、data 值、指针指向比肉眼猜快很多。很多卡了很久的空指针问题用调试器十分钟就能定位。数据结构学习过程中越早习惯调试器越好。2.3 学习节奏怎么定三种路线不同目标的人学这门课的方式不一样。我把它分成三条路线。路线一学校同步学。跟着老师每周进度看完对应讲次每讲至少写一个小实验。这种节奏最稳压力也最小。路线二期末突击。时间有限可以按“线性表 → 栈和队列 → 树 → 图 → 查找 → 排序”的顺序快进。重点是手工模拟题和算法框架细节代码可以暂时放一放但复杂度分析必须记牢。路线三考研或面试准备。第一遍可以稍微快一点但必须把基础打牢。第二遍做专题回顾第三遍刷题查漏。44 讲如果每天只看视频两三天就能刷完。如果每讲都停下来动手写代码可能需要三到四周。我更推荐后一种。数据结构这类课程代码能力和结构理解是强绑定关系动手越早后面越省力。3. 线性表与树基础结构决定代码上限3.1 顺序表与链表边界条件是第一道坎顺序表本质就是数组逻辑相邻的元素在物理上也相邻。链表通过指针把节点串起来逻辑上相邻物理上不一定连续。很多人只记住了“顺序表查找快链表插入删除快”这个结论是有前提的。顺序表随机访问是 O(1)但插入删除要搬移元素平均是 O(n)。链表要找指定位置得从头遍历查找是 O(n)如果已经持有前驱节点的指针插入删除可以做到 O(1)。真正的难点在链表的指针操作。写删除节点代码时你要先找到前驱 pre 和目标节点 p然后把 pre-next 指向 p-next再释放 p。很多人会把顺序写反先把 p 空间释放了结果后面访问到了非法内存。void deleteNode(LinkList L, int x) { LNode *pre L; LNode *p L-next; while (p ! NULL p-data ! x) { pre p; p p-next; } if (p ! NULL) { pre-next p-next; free(p); } }这段代码看起来简单但你要验证这几组用例链表为空删除的是第一个节点删除的是最后一个节点链表中有重复值只删除第一个。每一组都值得跑一遍。栈和队列可以看成受限的线性表。栈只能在一端进出队列在一端进另一端出。它们的应用很常见函数调用栈、浏览器后退、打印缓冲、任务调度。课程讲到这里时理解“操作受限”这个定位比硬背定义更实用。3.2 递归与二叉树画图比看视频更管用二叉树是最适合练习递归的结构。每个节点的左子树和右子树也是二叉树天然递归。先序遍历的代码非常短但如果你只盯着代码大概率看不明白。void PreOrder(BiTree T) { if (T ! NULL) { printf(%d , T-data); PreOrder(T-lchild); PreOrder(T-rchild); } }我建议你找一棵只有三个节点的二叉树在纸上手动走一遍打印根节点进入左子树打印左孩子再进入右子树打印右孩子。把这条路径走完先序、中序、后序的区别就清楚了。中序和后序只是把 printf 的位置换了一下但访问顺序完全不同。递归最常见的错误是把终止条件写错或者不判断空指针直接访问 T-data。还有同学会把 if 写成 while导致无限递归。遇到这种情况先看递归出口再看递归参数是否向出口靠近。树这块的坑也很多空树、只有根节点、只有左子树、只有右子树、完全二叉树、满二叉树。测试时要把这些情况覆盖到否则你以为代码写得对一提交就崩。3.3 哈夫曼树、表达式树与更多“树”哈夫曼树也叫最优二叉树目标是让带权路径长度 WPL 最小。构建方法是每次选权值最小的两个节点合并成一个新节点权值相加重复到只剩一棵树。考试常考给一组权值构造哈夫曼树然后算 WPL。这句话值得多读两遍因为手工模拟时很容易把合并顺序搞错。表达式树的叶子是操作数内部节点是操作符。对表达式树做后序遍历可以得到后缀表达式正好方便机器用栈求值。很多编译原理和计算器项目都会用到这个思路。课程后面还会涉及平衡二叉树、B 树、B 树、红黑树。平衡二叉树通过旋转保持高度平衡B 树适合磁盘存储树的高度越低越好红黑树是一棵近似平衡的二叉搜索树在很多语言的关联容器里都有应用。这些内容在 44 讲里可能只是引出但你在学的时候要意识到它们是同一棵“树”体系下解决不同问题的变体。另外“树”这个字在计算机领域很泛滥。比如嵌入式 Linux 里的设备树是描述硬件资源的结构网页可视化里的树图是数据展示组件。这些和数据结构的二叉树不是同一个东西。你看到“RK3568 设备树”这类话题时不要以为是自己漏学了哪一节。4. 图、查找与排序综合题的高发区4.1 图的存储与遍历是后续算法的前提图的内容主要分两块存储结构和算法。存储结构最常用的是邻接矩阵和邻接表。邻接矩阵用二维数组存边判断两个顶点是否有边很方便但稀疏图空间浪费严重。邻接表用链表存邻接顶点空间省遍历邻接点方便但要判断两个顶点之间是否有边需要遍历链表。图遍历的核心是 DFS 和 BFS。DFS 和树的先序遍历很像递归或用栈BFS 用队列逐层扩展。两者都需要一个 visited 数组防止重复访问。很多人写图遍历时忘记标记节点程序会一直循环或者遍历结果多出很多重复节点。这个标记动作不是可选项而是必备条件。图的应用题是大头。最小生成树里Prim 算法从点出发每次选代价最小的边加入Kruskal 算法按边权排序从小到大选不构成环的边。Dijkstra 求单源最短路径注意它不能处理负权边Floyd 求所有顶点对之间的最短路径能处理负权边但不能有负环。拓扑排序用来判断有向图是否有环在工程依赖、课程安排这类场景里很常见。AOE 网的关键路径对应项目管理和排期问题。学图的时候建议配合手工模拟。Dijkstra 的 dist 数组变化、Prim 的选边过程、Kruskal 的并查集判断都是考卷上的常见题。视频里看着简单自己动手写一遍才知道哪一步容易错。4.2 查找不是只背“折半能用二分”就行查找的核心不是“找到”而是“怎么找得快”。顺序查找最简单也最慢O(n)。折半查找要求数据有序且能随机访问数组适合链表不适合因为链表取中间位置要遍历效率提不上去。分块查找可以理解成折半和顺序之间的中间方案。动态查找里二叉排序树很重要。它的中序遍历有序正常使用下查找、插入都很快。但如果输入有序BST 会退化成链表查找效率掉到 O(n)所以才需要平衡二叉树来保证高度。AVL 是严格平衡的一种方案调整方式有单旋和双旋考试容易考到。B 树、B 树适合大量数据的磁盘存储。磁盘读写成本高树的高度越低越好。红黑树在工程里更常见很多标准库的 map、set 底层就是它。课程阶段不要求手写红黑树但要能理解它的作用把最坏情况控制在 O(log n)。哈希查找是另一种思路通过哈希函数直接计算存储位置。但哈希冲突无法完全避免经典处理方式有开放定址法、链地址法等。装填因子越大冲突概率越高所以实际使用时要预留空间。字典树Trie也值得注意它适合做字符串前缀匹配输入法联想、在线搜索提示这类场景经常用。4.3 排序复杂度、稳定性与应用选择排序可能是整套课程里最容易被“背回坑里”的一章因为算法太多每个都有名字、复杂度、稳定性。我更建议把它们先分成几类插入排序、交换排序、选择排序、归并排序和基数排序。算法平均时间复杂度最坏时间复杂度空间复杂度稳定性直接插入排序O(n²)O(n²)O(1)稳定希尔排序约 O(n^1.3)O(n²)O(1)不稳定冒泡排序O(n²)O(n²)O(1)稳定快速排序O(n log n)O(n²)平均 O(log n)不稳定简单选择排序O(n²)O(n²)O(1)不稳定堆排序O(n log n)O(n log n)O(1)不稳定归并排序O(n log n)O(n log n)O(n)稳定基数排序O(d(nr))O(d(nr))O(nr)稳定这张表的标准说法在不同教材里略有差异尤其是希尔排序和基数排序。但考试和面试最常考的还是快排、堆排、归并三个以及稳定性对整个排序过程的影响。快速排序平均性能优秀但基本有序时会退化到 O(n²)。原因是固定选第一个元素作基准时每次划分都极不均匀。实际工程里常用随机选基准或三数取中。堆排序的关键是堆的调整要会从最后一个非叶子节点开始向下调整建堆。归并排序需要辅助数组空间 O(n)但优点是稳定。为什么稳定性重要如果先按成绩排序再按姓名排序不稳定的排序算法可能把第一次成绩的先后顺序打乱。这种场景在按多个字段排序时很常见。学排序时建议每个算法都手动跑一组小数据比如 [5, 3, 8, 3, 2]记录每一轮结果。稳定性不同相同元素 3 的相对位置就能看得很清楚。5. 看课不是终点听一节、写一段、跑一次5.1 每讲结束后的三件事我强烈不建议一天看十几讲。44 讲看起来不长但如果只是“看”眼睛会了手不会。每讲结束后我建议你做三件事在笔记里用三句话概括这节课讲什么解决什么问题、用什么结构、代价是什么。把核心算法写在编辑器里不看视频自己实现一遍。跑一组测试数据至少包含正常、边界、空三个场景。如果代码没跑通就回到视频里看对应片段不要直接抄课件代码。很多同学连链表创建都跑不通过就开始学图的算法后面的所有实验都会变成一坨越堆越大的错。5.2 常用代码验证模板与测试用例设计学链表、二叉树、排序时可以准备一个目录把每个算法的核心函数单独放一个文件。测试时写一个最简单的 main输入固定数组打印过程观察输出。快速排序是复习时最好的例子void quickSort(int arr[], int low, int high) { if (low high) { int pivot partition(arr, low, high); quickSort(arr, low, pivot - 1); quickSort(arr, pivot 1, high); } }注意这只是一个框架partition 的实现要自己写。你可以把 partition 实现成单向扫描或双向扫描跑不同测试用例看效果。调试建议先打印每一轮排序后的数组确认分割点是否正确。不要一上来就加随机化先把基础版本跑通。测试用例不能只写一个正常输入。做链表题空链表和单节点必须有做树题空树和只有根节点必须有做排序题已经是升序、降序、含重复值的数据都值得跑。这些边界条件往往决定代码能不能扛住正式场景。5.3 实验报告和刷题怎么配合实验报告是学校数据结构课常见的作业也是帮自己梳理知识的好方式。一份有用的实验报告不要写成流水账至少包含问题场景、存储结构设计、核心算法流程、测试用例与运行结果、时间空间复杂度分析、踩到的 bug 和修复过程。真正加分的往往是最后的 bug 记录。学完一章后再去刷对应题。常见刷题平台上有“链表”“树”“二分查找”“排序”等标签按标签刷能快速把课程知识迁移到题目里。刚开始不要刷难题先做中等偏简单重点是验证自己能不能写出无 bug 版本。数据结构课程里学到的东西只有在自己独立写对之后才算真正掌握。6. 常见卡壳点与排查思路6.1 听懂了但写不出代码这个现象特别普遍。原因很简单视频里的代码是别人写好的你在看的时候没有经历“从问题到代码”的翻译过程大脑以为自己会了实际上只是识别了代码。解决办法是强制自己先画图再写代码。比如单链表反转先在纸上画三个节点手动走一遍指针变化再翻译成代码。画完图之后再处理空表和单节点。如果还是卡住就把任务拆小。先写一个能编译的 main再定义节点结构体再创建链表最后才写核心操作。问题范围缩小之后卡点的定位会清晰很多。6.2 运行崩溃和结果错误怎么查数据结构代码最常见的崩溃原因是空指针。比如对 NULL 取 data或者链表节点释放后再访问它的 next。出现这种情况时不要急着改代码按这个顺序排查先看程序卡在哪个函数、哪一行。打印或单步观察相关指针是否为空、数组下标是否越界。缩小输入用最小用例复现。检查边界条件空链表、单节点、首节点、尾节点。如果结果只是差一点重点检查对齐和更新顺序尤其是两个指针交换时。调试器是必须的。单步执行时能看到变量当前值比 printf 更直接。刚开始用可能觉得麻烦但排查两三个空指针问题后就会习惯。如果卡了很久也可以把代码放到一边重新画一遍结构图往往能发现问题出在指针指向已经变化了但变量名没变。6.3 几个带“树”字的名称不要混在一起课程学到后面“树”出现得越来越多二叉树、二叉排序树、平衡二叉树、哈夫曼树、B 树、B 树、红黑树、字典树。这本身是一棵“家族树”但成员用途差别很大。二叉树是基础普通存储任意数据二叉排序树加上了有序性平衡二叉树保持高度哈夫曼树解决压缩编码B 树解决磁盘 IO红黑树保证最坏情况稳定字典树是字符串前缀处理。另外还有一些完全不同的“树”。比如嵌入式开发里经常提到的设备树用于描述硬件设备和数据结构里的树结构不是同一个东西。如果你看到“RK3568 设备树”之类的搜索词对不上课程内容不要怀疑自己学漏了那只是同名概念。7. 期末、考研和面试怎么衔接这套课7.1 期末复习先抓手工模拟和算法设计期末复习建议分两部分。第一部分是手工模拟题。考试经常会给你一组关键字要求构造哈夫曼树、写快速排序每轮结果、构造二叉排序树、模拟哈希表冲突处理、用 Dijkstra 求最短路径。这些题不需要你写完整代码但要求你按算法步骤一步步走。第二部分是算法设计题。常见类型链表反转、删除指定节点、合并有序链表二叉树遍历、求深度、判断平衡数组的查找和排序图的深度优先、广度优先遍历。复习时每个类型准备一个模板。做题时先判断输入是什么输出是什么用顺序结构还是链式结构递归还是迭代复杂度要求多少。这套判断流程比背代码重要得多。考试时一旦判断错结构后面代码写得再顺也拿不到分。7.2 考研和面试建议考研复习一般会用综合资料做强化很多人提到“王道”系列。我的建议是第一遍用这套 44 讲补基础建立框架第二遍用考研资料按专题强化重点放在复杂度分析、手工模拟和算法设计第三遍做真题和模拟题把错题归到对应章节再回头翻看视频中的相关内容。面试准备则可以换个思路。常见高频题往往是这样指针题单链表反转、链表判环、合并两个有序链表。树题二叉树层序遍历、验证二叉搜索树、最近公共祖先。查找题二分查找的边界处理、前缀树实现。结构题LRU 缓存通常用哈希表 双向链表。这些题背后都是课程里的知识只是穿上了工程化的外衣。学完数据结构后再去刷这些题目会比直接硬刷顺畅很多。这套 44 讲课程不是看完就结束的资源。真正决定学习效果的是你有没有在每讲之后动手写代码、设计测试、记录踩坑。把单链表、二叉树遍历、图遍历、折半查找、快速排序这些基础算法写到能默写的程度后面再学算法分析、操作系统、数据库和工程开发都会轻松不少。数据结构是计算机专业的底座底座稳不稳就看你有没有把代码一次一次跑起来。
返回列表