algorithms 分类归档

共 127 篇文章 · 返回首页

整数压缩:varint、Golomb、PForDelta 与 SIMD 位打包,倒排表里每个整数花几比特

以倒排表的 d-gap 为对象,在两份真实语料和伯努利合成表上实测 varint、Elias、Golomb/Rice、插值编码、Elias-Fano、Simple、PFOR、Stream VByte、BP128 的每整数比特数与下界之差,并在共享 2 vCPU 上测解码的相对速度。

时序数据压缩:delta-of-delta、XOR 浮点编码与十进制数据上的失效

拆解 Gorilla 的时间戳 delta-of-delta 与浮点 XOR 编码,对照 Prometheus、InfluxDB、VictoriaMetrics 钉版本源码,用节点采集数据和 ALP 数据集实测每个值花多少比特,并说明 XOR 在十进制数据上失效的原因与 Chimp、Elf、ALP 的改法。

LZ77、LZ78 与 LZW:字典从哪里来,最长匹配怎么找

从 1977、1978 年两篇原始论文出发,讲清滑动窗口与短语表两种字典、LZSS 与 LZW 的改动;用可解码验证的固定码 DEFLATE 输出实测哈希链与二叉树匹配查找器、贪心/lazy/最优解析:二叉树每位置 22 个候选即得最长匹配,最优解析比贪心小 12.7%。

zstd 的格式与实现:序列、FSE 表、字典与长距离匹配

按 RFC 8878 与 zstd 1.5.7 源码拆开帧、块、字面量段和序列段,讲清 FSE 表怎么建、怎么传、编码器怎么选模式;用逐比特记账的解码器实测:偏移额外比特占 39–44%,FSE 离逐块经验熵不到 1%,字典与长距离匹配的收益取决于数据和编码器的启发式。

算术编码、Range Coder 与 ANS:分数比特的记账方式与精度损失

算术编码、range coder、rANS、tANS 怎样让每个符号只花分数比特,有限精度的损失落在频率量化、区间截断、状态下界、表的排布和收尾字节中的哪一处;用逐比特记账的可复现实验量化离熵多远,并讨论自适应建模、专利与 tANS 建表的开放问题。

Epoch-Based Reclamation:两个纪元的由来、Crossbeam 的实现与停顿的代价

从 Fraser(2004)的三个 limbo list 出发,推导 EBR 为什么要等两个纪元、垃圾该打哪个纪元的标签;对照 crossbeam-epoch 0.9.18 源码,实测两个变异体、pin 的指令选择、每节点开销、回收速率上限,以及一个被抢占或睡住的读者让垃圾涨到多少。

路由算法:距离向量、链路状态与路径向量的收敛与稳定性

在同一 8 节点拓扑上模拟距离向量、链路状态、路径向量在链路故障和目的地失效后的收敛轮数与消息数,对照 RFC 2328、RFC 4271 与 Labovitz、Griffin 等论文,解释 LSA 泛洪、MRAI、路由震荡抑制、策略不收敛和快速重路由各自解决什么、代价是什么。

并发跳表:标记删除、乐观加锁与 ConcurrentSkipListMap

跳表插删要改多个指针,靠标记删除或乐观加锁把它们变成一次线性化操作。对照 Pugh、Harris、Fraser、HLLS 与 JDK 21、LevelDB、RocksDB 源码,并用 TSan 与对拍验证实现,实测独占 CPU 与超额订阅两种情形下的吞吐。

负载均衡算法:P2C、平滑加权轮询与过时负载信息

从球箱模型与超市模型出发,用离散事件模拟比较随机、轮询、P2C、JSQ 在新鲜与过时负载信息下的平均与 p99 逗留时间,再对照 NGINX 1.26.2、Envoy v1.31.0、gRPC、Finagle 与 Prequal 说明各策略的真实实现与适用边界。

学习索引:RMI、PGM-index、ALEX 与调优 B+tree 的真实差距

把有序数组查找看成拟合 CDF:梳理 RMI 到 PGM-index、ALEX、LIPP 的谱系,用可复现程序在四种分布上比较比较次数、缓存行与索引大小,并对照 SOSD、GRE 基准:学习索引在只读、易拟合数据上领先,写密集、难分布与并发下优势收窄。

滑动窗口与流量控制:ARQ 效率、序号空间与 TCP/QUIC 的接收窗口

从停等、GBN、SR 的效率推导与丢包模拟出发,说明窗口为何要覆盖 BDP、SR 为何只能用一半序号空间,再按 RFC 9293、RFC 9000、RFC 9113 与 Linux 6.12 源码拆解 TCP、HTTP/2、QUIC 的接收窗口与自动调优。

基数排序:绕开比较下界的代价,从 LSD、American flag sort 到 ska_sort

比较下界只约束比较模型,基数排序把代价转移到键长和内存访问上。本文推导代价模型,用缓存模拟与绑核实测解释位宽为何停在 8 到 11 位,并对照 ska_sort、ClickHouse、DuckDB 与 IPS²Ra 说明它何时赢、何时输。

并行排序:排序网络、并行归并、样本排序与 GPU 基数排序

用 work/span 计数解释并行排序为何难以线性加速:串行归并与串行划分把并行度压在个位数,并行归并、Merge Path 与样本排序各自如何突破;再对照 libstdc++、oneTBB、Rayon、CUB 源码看生产实现的真实选择。

Bloom Filter 家族:从位数组到 Ribbon,每键位数离下界还差多少

用可复现实验测量 Bloom、分块 Bloom、cuckoo、xor 与 Ribbon 的每键位数和误判率,对照 log2(1/ε) 下界解释 1.44 倍从何而来、经典 FPR 公式偏在哪里,并核对 RocksDB 9.10 的 FastLocalBloom 与 Ribbon 实现。

红黑树与 AVL:旋转次数、树高与 Linux 内核的选择

用可复现的计数实验(红黑树部分与 Linux v6.12 lib/rbtree.c 逐操作一致)比较 AVL、红黑树与左倾红黑树的树高、旋转、平衡标记写入和比较次数:AVL 与红黑树平均差距很小,差在删除的最坏情形;并核对内核从 AVL 换到红黑树、再把 VMA 交给 maple tree 的史实。

van Emde Boas 树:整数前驱查询的递归结构、空间代价与下界

vEB 树把 w 位整数键逐层对半拆分,使前驱查询每层只递归一次,代价是与宇宙大小成正比的空间。本文给出经穷举测试的 C 实现,用调用次数、字节数和绑核计时对比 std::set 与 64 叉分层位图,并梳理从 1975 年原论文到 Pătraşcu–Thorup 下界的谱系。

Merkle 树与认证数据结构:包含证明、一致性证明与构造陷阱

按 RFC 9162 实现 Merkle 树哈希、包含证明与一致性证明并用公开向量验证,复现域分离缺失与 Bitcoin CVE-2012-2459 两类缺陷,实测 k 叉 trie 证明大小,梳理从 Merkle 1979 到 Verkle 与二叉状态树之争。

编辑距离与模糊匹配:Wagner-Fischer、位并行与 Levenshtein 自动机

从 Wagner-Fischer 填表出发,讲清带状 DP、Myers 位并行、OSA 与真 Damerau 的区别,用可复现程序在 8 万词词典上对比 BK-tree、Trie 自动机与对称删除,并核对 Lucene、git 的实际实现与 SETH 下界。

字符串哈希:Rabin-Karp、滚动哈希与内容定义分块

滚动哈希的保证来自输入确定后才随机选的素数、基或不可约多项式。本文按 Karp-Rabin 原文推导碰撞界,实测 Thue-Morse 串攻破 2^64 自然溢出,并用 LBFS、FastCDC、restic、borg 的源码与模拟说明内容定义分块。

HyperLogLog:从概率计数到 Redis 实现的基数估计

12 KB 的 HyperLogLog 误差从哪来:沿 FM85、LogLog、HLL、HLL++ 到 Ertl 估计器推导,用 1000 次模拟实测各代估计器在小、中、大基数上的偏差,并对照 Redis 7.2.5 源码拆解稀疏/密集编码和三次更换的估计公式。

t-digest:缩放函数、合并与尾部分位数误差

t-digest 用缩放函数限制质心大小,换来极小的尾部秩误差,但没有最坏情形保证。本文对照 Dunning 与 Ertl 预印本及 Elasticsearch、ClickHouse 源码,用可复现实验测量尾部误差与合并顺序的影响,并复现让误差达到约 40% 的困难分布。

水塘抽样:Algorithm R/L/Z、加权键与样本合并

水塘抽样要保证的是每个 k 子集等概率。本文严格证明 Algorithm R,从随机键推出 Li 的 Algorithm L,用卡方检验与随机数计数对比 R、L 与 Vitter Z,核对 PostgreSQL 17 与 Spark 3.5 源码,并讨论加权键、样本合并与滑动窗口。

流式算法总论:数据流模型、频率矩下界与线性 sketch

一遍扫描、内存远小于数据时能算什么:梳理三种流模型、Morris 到 AMS 与 Indyk 的谱系、通信复杂度下界,实测 AMS F2 sketch 误差随计数器数的变化,说明线性 sketch 为何可合并、可删除,并把本系列 30 到 35 篇串成路线图。

最小生成树:割性质、Kruskal/Prim/Borůvka 与线性时间开放问题

从允许并列边的割性质与环性质出发,给出 Kruskal、Prim、Borůvka 的正确性条件与分步图,用可复现程序按比较次数、decrease-key 次数和计时对比三者,并梳理从 1926 年到 Chazelle、Pettie–Ramachandran 的谱系与确定性线性时间开放问题。

哈希表内部:链式、线性探测、Robin Hood 与生产实现的取舍

用可复现的探测次数模拟核对 Knuth 的线性探测公式,比较链式、线性探测、Robin Hood、双重哈希与 SwissTable 分组探测的探测分布和删除策略,再对照 CPython 3.13、JDK 21、Go 1.23/1.24、Abseil、Redis 7.4 的源码说明各自的取舍。

密码学哈希与非密码学哈希:安全定义、迭代构造与哈希洪泛

区分非密码学哈希、带密钥 PRF 与密码学哈希三种契约;用可复现实验演示 SHA-256 长度扩展、雪崩测试的局限、DJBX33A 与带种子 MurmurHash3 的哈希洪泛,并对照 CPython、Rust、Go、Abseil 源码说明各自默认哈希。