现代 C++ 实战(22):图算法
第 21 篇 的树是一对多分支;图则允许任意顶点之间连边——社交网络、路由表、任务依赖、编译单元关系,本质都是图。BFS 找最短、DFS 探路径、Dijkstra 算权重、拓扑排序排依赖——四大经典算法覆盖 90% 的工程场景。 demo:ref/cpp_demo/algorithms/graph/(graph.h、bfs、dfs、dijkstra、topological_sort)。 这是「现代 C++ 实战」系列的第 22 篇。建议先读 第 21 篇:树结构全家桶。 一、图的两种表示顶点 V、边 E。两种存储方式,时空权衡不同: 表示 空间 查边 遍历邻居 适用 邻接矩阵 O(V²) O(1) O(V) 稠密图、频繁查边 邻接表 O(V+E) O(度) O(度) 稀疏图、遍历为主 123456邻接矩阵(6 顶点) 邻接表 0 1 2 3 4 5 0 → [1, 2]0 [ 0 1 1 0 0 0 ] 1 → [3]1 [ 0 0 0 1 0 0 ] 2 → [...
x86 汇编入门(04):循环与条件跳转
高级语言里写 for (i = 1; i <= 10; i++) 一行搞定。汇编里没有 for,只有比较 + 跳转。这一篇用 04_loop.asm 打印 1 到 10,把循环拆成你能看见的每一步。 这是「x86 汇编入门」系列的第 4 篇。上一篇实现了算术和数字打印。这一篇通过 04_loop.asm,学习条件跳转指令和循环结构的汇编写法。 一、比较与跳转cmp a, b 做减法但不保存结果,只设置 CPU 标志位。然后根据标志位跳转: 指令 条件 je 相等 (ZF=1) jne 不相等 jl 小于(有符号) jle 小于等于 jg 大于 jge 大于等于 jmp 无条件跳转 二、用跳转拼出循环04_loop.asm 的逻辑等价于: 123for (int i = 1; i <= 10; i++) { printf("当前数字: %d\n", i);} 汇编实现: 1234567891011121314mov r12, 1 ...
大模型数学速成(07):RoPE——用旋转编码位置
Self-Attention 本身不包含位置信息——打乱 token 顺序,只要 Q/K/V 一起打乱,注意力分数不变。但语言有语序:「狗咬人」≠「人咬狗」。位置编码告诉模型每个 token 在序列中的位置;现代 LLM 广泛使用的 RoPE(Rotary Position Embedding,旋转位置编码) 通过「旋转」Q/K 向量来注入相对位置。 这一篇搞懂:为什么需要 RoPE、旋转在算什么、为何只改 Q/K、以及绝对位置与相对位置的关系。 这是「大模型数学速成」系列的第 7 篇。建议先读 第 06 篇:FFN。下一篇 ViT 层 vs LLM 层对照总表。 一、顺序问题:Attention 是「置换等变」的第 05 篇 的注意力只看点积相似度。若把 token 列整体重排(Q、K、V 同步重排),每个 token 关注谁不变——模型不知道谁在前谁在后。 早期做法: 方法 思路 代表 绝对位置嵌入 给每个位置 $i$ 学一个向量 $p_i$,$x + p_i$ 原始 Transformer RoPE 按位置旋转...
现代 C++ 实战(21):树结构全家桶
第 20 篇 的链表是「一对一」串联;树则是一对多的分支结构。从二叉搜索树到 AVL、红黑树、B 树、堆——五种经典树形结构,覆盖了内存索引、STL 容器、优先队列和磁盘存储的核心场景。 demo:ref/cpp_demo/algorithms/tree/(binary_tree、avl_tree、red_black_tree、b_tree、heap)。 这是「现代 C++ 实战」系列的第 21 篇。建议先读 第 20 篇:栈、队列与链表。 一、五种树,一张选型地图 结构 平衡策略 查找 插入 典型场景 BST 无保证 O(h) O(h) 教学、小规模有序数据 AVL 严格平衡 O(log n) O(log n) 查找密集、更新较少 红黑树 近似平衡 O(log n) O(log n) std::map / std::set B 树 多路平衡 O(log n) O(log n) 数据库索引、文件系统 堆 堆序性质 O(n) 查任意 O(log n) 优先队列、Top-K 12345678910111213BST(可能退化成链) ...
x86 汇编入门(03):算术运算与数字转字符串
终端只能显示字符,不能直接显示数字 42。所以汇编里做算术只是第一步,更麻烦的是把结果「翻译」成 '4' 和 '2' 再送出去。这一篇我们练四则运算,并实现一个可复用的 print_number 子程序。 这是「x86 汇编入门」系列的第 3 篇。前两篇解决了输出字符串和读取输入。这一篇通过 03_calc.asm,掌握算术指令和整数转 ASCII 的核心技巧。 一、基本算术指令对两个常数 42 和 8 演示四则运算: 指令 含义 示例结果 add dst, src 加法 42 + 8 = 50 sub dst, src 减法 42 - 8 = 34 imul dst, src 有符号乘法 42 × 8 = 336 idiv src 有符号除法 42 ÷ 8 = 5 … 2 除法要特别注意:idiv 用 rdx:rax 作为被除数。执行前需要 cqo 把 rax 符号扩展到 rdx: 1234mov rax, num_acqo ...
大模型数学速成(06):前馈网络 FFN——GELU 与 SwiGLU
上一篇里,每个 token 通过注意力「看过」其他 token。但注意力只做加权混合——线性组合 V,表达能力有限。Transformer 块的另一半是 FFN(Feed-Forward Network,前馈网络):对每个 token 独立做「升维 → 非线性 → 降维」,注入更强的逐 token 变换能力。 这一篇搞懂 FFN 在算什么、GELU / SwiGLU 是什么、以及 ViT 与 LLM 的常见差异。 这是「大模型数学速成」系列的第 6 篇。建议先读 第 05 篇:注意力与 Softmax。下一篇讲 RoPE 位置编码。 一、注意力 vs FFN:分工不同 Self-Attention FFN 跨 token ✅ token 之间交换信息 ❌ 每个 token 独立处理 主要操作 加权求和(线性) 矩阵乘 + 非线性激活 类比 开会对齐信息 会后各自消化、深度加工 形状 [d, S] → [d, S] [d, S] → [d, S] 完整 Transformer 子层(Pre-LN)典型顺序: 1x → Norm → At...
现代 C++ 实战(20):栈、队列与链表
第 19 篇 的哈希表用数组 + 指针组织数据;再往前退一步,有三种几乎无处不在的基础结构:栈(LIFO)、队列(FIFO)、链表(动态串联节点)。实现简单,却是表达式求值、BFS、LRU 的底座。 demo:ref/cpp_demo/algorithms/stack_queue_list/(stack_demo、queue_demo、linked_list_demo)。 这是「现代 C++ 实战」系列的第 20 篇。建议先读 第 19 篇:哈希表。 一、三种结构一句话 结构 规则 典型操作 栈 Stack 后进先出 LIFO push / pop / top 队列 Queue 先进先出 FIFO enqueue / dequeue / front 链表 Linked List 节点 + 指针串联 头插、尾插、删除、遍历 12栈: push → [30][20][10] ← top 队列: front → [10][20][30] ← back链表: head → (30) → (20) → (10)...
x86 汇编入门(02):读取用户输入
上一篇程序只会「说」,不会「听」。真实程序几乎都要处理输入——命令行参数、用户键入、网络数据,本质都是往缓冲区里塞字节。这一篇我们学 sys_read,并认识汇编里的第三个地盘:.bss 段。 这是「x86 汇编入门」系列的第 2 篇。上一篇用 sys_write 输出了 Hello World。这一篇通过 02_input.asm,实现读取键盘输入并回显。 一、三段式内存布局到本篇为止,汇编程序的「地盘」凑齐了: 段 用途 类比 .data 已初始化的常量(字符串、数字) 写死在程序里的便签 .bss 未初始化的变量(缓冲区) 运行时用的空白草稿纸 .text 可执行指令 操作步骤 .bss 里的空间在程序加载时自动清零,用 resb N 预留 N 个字节: 12section .bss name_buf resb 64 ; 预留 64 字节缓冲区 二、sys_read 怎么用?sys_read 是 sys_write 的镜像操作: 寄存器 含义 rax 0(调用号) rdi 文件描述符(0 = st...
大模型数学速成(05):注意力机制与 Softmax
上一篇我们有了 Norm 与残差;第 03 篇我们算出了 Q、K、V。现在进入 Transformer 的核心:每个 token 用 Q 去「查询」全序列的 K,按匹配度加权混合 V。 这一篇把 注意力分数、Softmax、输出混合 的公式与手算例子讲清楚,并区分 Self-Attention 与 Cross-Attention。 这是「大模型数学速成」系列的第 5 篇。建议先读 第 04 篇:LayerNorm 与残差。下一篇讲 前馈网络 FFN。 一、图书馆检索三步把 第 03 篇 的图书馆类比补全: 步骤 数学 生活类比 1. 匹配 $Q$ 与每个 $K$ 算相似度 → scores 你的检索便签与每本书脊标签比对 2. 归一化 Softmax → 权重(和为 1) 把分数变成「借哪几本、各占多少比例」 3. 混合 按权重对 $V$ 加权求和 → 输出 把选中书的正文按比例拼成一份摘要 三步走完,每个 token 的输出不再只是「自己长什么样」,而是融入了它选择关注的其他 token 的信息。 二、符号与形状(列 = token)沿...
现代 C++ 实战(19):哈希表实现
第 18 篇 用 std::sort 做 O(log n) 查找前的准备;哈希表把查找压到平均 O(1)——键经哈希函数映射到桶,碰撞用链地址或开放寻址解决。理解这两条路,就摸清了 std::unordered_map 的底层地图。 demo:ref/cpp_demo/algorithms/hash_table/(链地址、线性探测、双重哈希 + 与标准库性能对比)。 这是「现代 C++ 实战」系列的第 19 篇。建议先读 第 18 篇:排序算法。 一、哈希表在干什么? 操作 平均时间 思路 插入 O(1) index = hash(key) % bucket_count 查找 O(1) 同 index,再比对 key 删除 O(1) 定位后删节点或标记槽位 碰撞(collision):不同 key 算出同一 index。解决策略分两大类: 12链地址法: bucket[i] → (k1,v1) → (k2,v2) → …开放寻址: table[i], table[i+1], … 在同一数组里探测下一个空位 二、哈希函数好哈希函数:确定性、均匀分...















