从这一课起,我们进入第三个阶段:并发与同步。前面我们认识了进程、线程这些"演员",现在要回答一个更现实的问题:舞台上只有一块 CPU,几十个"演员"都想上,该让谁上、上多久? 这个"排班"的工作,就交给CPU 调度。从"为什么感觉程序在同时跑"说起你同时开着浏览器、音乐、编辑器。可你的电脑可能只有一个 CPU 核。一个核,同一时刻只能跑一个进程——那凭什么你觉得它们"同时在跑"?答案是:CPU …

前面几课,我们认识了进程、线程、fd、fork/exec、信号。但你有没有发现一个问题:这些"孤岛"之间,怎么交换数据? 进程 A 算出一个结果,进程 B 怎么才能拿到?这一课,我们就来解决进程之间"说话"的问题——进程间通信(IPC,Inter-Process Communication)。从"ls | wc"说起你在终端敲下:ls | wc -lls 列出当前目录的文件,wc -l 数一数 …

到目前为止,我们学的结构都是一条线(数组、链表)或一棵树(二叉树)。但现实里很多东西是网状的:社交网络:A 关注 B,B 关注 C,C 又关注 A……城市地图:道路把一个个路口连起来,能绕圈网页链接:页面互相指向,构成一张巨大的网这些"节点 + 任意连线(可以有环)"的结构,就是图(graph)。它是最通用的数据结构——链表和树,都只是图的特例。这一课,我们学图怎么存、怎么遍历,掌握 BFS …

想象一个场景:医院急诊室。病人源源不断地来,但病情重的必须先看,不能简单按先来后到排队。你需要一个数据结构,它能做到——随时把"最急的那个"拎出来,新病人来了随时插进去。这个"永远知道谁最大/最小"的数据结构,就是堆(heap)。它是优先队列(priority queue)的实现方式,也是很多算法(topK、Dijkstra、任务调度)背后的功臣。一、优先队列是什么:会"插队"的队列第 2 课 …

前面学的数组、链表、栈、队列、哈希表,数据都是"一条线"排开的。但现实里很多东西天生是分叉的:公司组织架构:一个 CEO 下面一堆 VP,每个 VP 下面又带几个总监……文件夹结构:一个目录里有子目录,子目录里还有子目录……网页的 HTML:<body> 里套 <div>,<div> 里又套 <p>……这些"一个上级、多个下级"的结构,用一条线表 …

想象一个游戏:我心里想一个 1 到 100 之间的数,让你猜,我只能回答"大了""小了""对了"。你怎么猜最快?绝大多数人第一次会从 1 开始:1?2?3?……最倒霉要猜 100 次。聪明人这么猜:先猜 50。"大了"→ 说明在 1~49,"小了"→ 说明在 51~100。每次猜中间那个数,每猜一次,范围砍掉一半。100 个数,最多 7 次就锁定答案。这个"每次砍一半"的策略,就是二分查找(b …

你在终端跑着一个程序,眼看它卡住了,你下意识按下 Ctrl+C——它停了。又或者,你发现某个进程怎么都杀不掉,于是掏出 kill -9,它立刻毙命。这些"远程遥控"背后,靠的都是同一个机制:信号(Signal)。这一课,我们认识这个进程之间的"通知系统"。从"按 Ctrl+C"说起你正跑着一个死循环程序,屏幕上刷着一行行输出。你按 Ctrl+C,程序停了。这一瞬间到底发生了什么?很简单:你的按 …

上一课结尾我留了个问题:你在 shell 里敲下 ls,那个 ls 进程是怎么"变"出来的?答案是一对黄金搭档——fork 和 exec。一个负责"复制",一个负责"变身"。这一课,我们把这对搭档彻底拆开。从"敲下 ls 的瞬间"说起你敲下 ls -l,回车。屏幕上列出了一堆文件。你有没有想过:ls 是一个躺在磁盘上的程序,它是怎么变成一个正在运行的进程的?难道 shell 自己"变身"成 l …

前面几课我们都在跟"数据结构"和"算法套路"较劲。这一课换个口味,聊点纯数学——但别慌,是程序员真正用得上的那部分,叫数论(Number Theory)。数论听起来高冷,实际上你早就天天在用:密码学的 RSA 加密靠质数,哈希表取模靠余数,加密与随机数生成靠最大公约数。哪怕是 LeetCode 上,也有一大类题直接考质数、公约数、模运算。这一课的目标:给你一个"算术工具箱",装进四件最常用的工 …

上一课讲排序时,我们偷偷用了一个"作弊"的招数:归并排序里,函数自己调用了自己——merge_sort 里面又调 merge_sort。这招有个正式的名字,叫递归(recursion)。它是算法世界里最优雅、也最让人头疼的思想之一:写对了代码短得惊人,写错了递归爆栈、死循环。这一课,我们把递归和它最经典的搭档——分治——彻底讲透。一、递归是什么:函数自己调用自己先看一个最简单的例子——算阶乘 …