“写笔记”支持四种格式——Word 文档、Excel 表格、Markdown、纯文本,起稿或二次编辑时都能随时切换,同一篇笔记想用哪种形态来记,都由你说了算。
md、txt、csv、json 这类纯文本则原样载入,不做多余加工。拿一张现成的表倒进来、改几笔、再导出去,等于白用一台免费的格式转换器。
要带走就在右上角点“下载”,可导出 PDF、Word、Markdown、Excel、TXT 等格式;列表卡片“⋯”菜单里,也有同样的下载入口。
在“工具”页点“+ 上传工具”即可发布:填好名称与链接,再用 Markdown 把使用方法写清楚——能解决什么问题、怎么装、怎么用,比堆介绍实在。
要分发安装包就一并上传压缩包(ZIP、RAR、7Z、TAR.GZ,最大 35MB),别人在详情页一键下载;只放链接不带附件也可以。
工具按大家的收藏热度排序,好用的自然会被顶上来。发布后可在详情页或卡片菜单里编辑、下架。
写笔记时勾上“隐藏”,这篇就只存在于你自己的账号里:不进列表、不进搜索、不上首页精选,也不会出现在任何公开的页面,链接发给别人同样打不开。
适合放密码、草稿、日记这类只给自己看的内容;想公开,去“发布”打开它,把“隐藏”的勾去掉再保存,之后编辑会默认保持原状态,不会悄悄变回公开。
你的内容会同时保存在多个副本上,系统定期做备份与完整性校验,再配合异地容灾机制:就算某台机器出问题,数据也不会丢,可以长期放心存放;特别重要的资料,仍建议你另外再留一份备份。
全站跑在容器化、模块化的现代架构上,更新、部署、回滚都很快,扩展性和稳定性都按长期运营的标准来设计(Built for reliability, designed to scale)。
这个网站最早只是一个人的笔记仓库,后来慢慢长成现在的知识中枢。设计上很克制——没有广告、没有追踪、没有推荐算法,只是干干净净地存放一些东西;既然做好了,就公开出来,万一有人用得上呢。
不做大而全,不做平台梦,保持简单、保持克制、保持好奇。所有内容都由用户贡献、由用户维护:不会突然冒出付费墙,不会在角落塞广告位,也不会把你的数据卖给第三方。
产品会持续迭代,站内日志页记录着每一次改动,改了什么都有迹可循;想了解这个站是怎么一步步走到今天的,翻翻日志就能看到来龙去脉。
如果在这里看到涉嫌违规的内容,点对应卡片右侧的“举报”按钮就能提交,我们会尽快核实处理;也谢谢你花一点时间,一起把这里维护干净。
HN 热帖:那些酷炫但小众的数据结构
本文总结 Hacker News 上关于“鲜为人知但很酷的数据结构”的讨论,涵盖布隆过滤器、跳跃表、默克尔树、RETE 网络、Trie、van Emde Boas 树等,并深入分析其原理、适用场景与对比。
引言
原帖是 Ask HN 上的一则提问,作者想了解社区中认为“酷但冷门”的数据结构。帖子获得了 2000+ 分和 700 多条评论,说明这个话题在极客圈子里很受欢迎。评论区贡献了许多有深度、有见地、充满工程智慧的数据结构案例,远超教科书范围。下面我按类别整理并深化讲解这些结构。
1. 布隆过滤器(Bloom Filter)及变体
作者最先抛出布隆过滤器:它可以用极紧凑的空间表示一个集合,支持查询“某个元素一定不在集合中”或“可能在集合中”,查询和插入的时间复杂度为 O(k),k 是哈希函数个数,与集合大小无关。
典型例子:路由器的黑名单 IP 检查。若比较 100 万个 IP,朴素做法逐一比对,时间复杂度随列表增长;而布隆过滤器不需要存储键本身,只要有固定数量的哈希函数,插入和查询都立刻完成,代价是可能有误报(false positive)但绝无漏报。
评论区补充的高阶变体:
- 可计数布隆过滤器(Counting Bloom Filter):支持删除操作,但会额外占用 4~8 倍空间。
- Blocked Bloom Filter:将布隆数组分为块,利用 CPU cache 局部性,速度更快(常用于高性能缓存系统)。
- Cuckoo Filter:比标准布隆过滤器更紧凑,支持删除,且查询性能更优,但实现复杂。
- Golomb Coded Sets(GCS):与布隆类似,但用 Golomb 编码压缩集合元素,空间更小,但查询、插入更慢。常用于 Bitcoin 节点间的交易过滤。
2. 跳跃表(Skip List)
跳跃表以概率化的方式维护有序链表,在多层链表上建立索引,平均 O(log n) 的时间复杂度,非常优雅地实现了二分查找性质。
评论区指出,跳跃表最常见的应用是 Redis 的 Sorted Set 内部实现。为什么 Redis 不用平衡树?因为跳跃表实现简单、容易调试、对内存更友好(节点共享概率),且在高并发下容易做锁粒度控制。
另一个有趣视角:跳跃表对 cache 不友好,因为节点分散内存;但它的局部更新成本低,对无锁编程、并发环境比平衡树更友好。
3. 默克尔树(Merkle Tree)及 Patricia Trie
默克尔树的核心优势是:根哈希能代表整个数据集状态,任何叶子节点改动都会向上传导导致根哈希变化。这带来了极高效的校验能力:只需同步 O(log n) 个哈希即可验证数据块的完整性。
评论者强调:默克尔树不单用于加密货币(比特币、以太坊),它也在分布式文件系统、内容寻址存储(如 IPFS)中扮演核心角色。讨论中还提到 Patricia Trie(压缩前缀树)如何配合以太坊的状态存储应对大量前缀相同的地址,也同时提到 radix tree 在 Linux 内核中用于 page cache 管理——它用稀疏数组高效维护密集合键值对。
4. RETE 算法 / RETE 网络(Rete Algorithm)
这是本次评论中最具“冷门”属性的一项:RETE 是规则引擎和专家系统中使用的模式匹配算法,其数据结构的核心是一个有向无环图(DAG),节点代表模式,边代表变量绑定关系。
当年著名的规则引擎 Drools(工业级)、JBoss Rules 都基于 RETE。它解决的核心问题是:当事实集合变化很小的增量时,快速找出所有匹配规则的组合。它的妙处在于“记忆中间匹配结果”,只重算变化的部分,这在现实业务规则引擎里大幅减少重复计算。
评论者提到,RETE 需要很多内存,且不适合规则经常变动的场景,但非常擅长静态规则下的海量事实匹配。
5. Trie 及其变体(Patricia、基数树、DAWG)
堆中最常见的 Trie 讨论是它在词典、自动补全、IP 路由匹配等领域的使用。此外 Patricia Trie 通过合并一叉分支节点压缩路径,大幅减少节点数。一个特别的观点:**最小化 Acyclic Finite-State Automaton(DAWG)**能存储大量字符串字典(英文整篇词典)只占很小的空间,因为共享前缀同时共享后缀,是单词字典达到最紧凑状态的最优结构,比 TST 省空间,但构建成本高。
6. van Emde Boas 树(vEB Tree)
这是真正“教科书之外的瑰宝”。vEB 树是一种用于整数集合的数据结构,能实现所有基本操作(插入、删除、查询、后继、前驱)在 O(log log U) 时间内完成,U 是全集大小。递归分块思想:将集合按平方根分块,每一块内部又是一个 vEB,顶层维护块索引。
一位评论者把它比喻为“在字典中利用平方根递归不断将复杂度压到 log log”,并指出实际工程中很少见,主要因为记忆体开销太大,但它是学习递归结构和复杂度分析最好的例子。它也是很多高性能稀疏计算库的决策参考。
7. 操作变换(Operational Transformation,OT)与 CRDT 数据结构家族
评论区后来转向并发协作编辑方向。OT 常用于 Google Docs 早期实现,核心结构是“已发送操作的日志、缓冲区 + 变换函数”。而 CRDT(Conflict-free Replicated Data Type)提供更优雅的无锁定解决冲突:每个副本维护状态,当并发操作出现时可按语义合并结果。
讨论涉及 CRDT 在 Yjs 中使用的数据类型,如 YATA(Yet Another Transformation Approach)——这是一个保持因果序的链表结构,也是 Yjs 底层核心,能支持十人同屏编辑而不冲突。这里的本质问题是:如何在多副本网络分区情况下保持一致性和收敛性,CRDT 给出数学上可证明的答案。
8. 最小堆/最大堆以外的堆变体:Pairing Heap、Fibonacci Heap、Binomial Heap
评论区专门讨论了Pairing Heap 的优点:代码极短,摊销复杂度接近 Fibonacci Heap(某些操作甚至更好),数据结构只需两个链接指针,非常适合算法竞赛实现。而 Fibonacci Heap 在理论上提供了 O(1) 的 decrease-key 和 merge,但实现复杂且常数因子高,在实际工程中几乎无人使用。这引起另一层讨论:理论优美性与实践简洁性之间的权衡,不能一概而论。有的评论者说:“选择数据结构有时是在跟硬件、缓存、页错误打交道,而不仅是大O复杂度。”
9. 时空权衡类:LSM Tree(Log-Structured Merge-Tree)
对于数据库爱好者,评论区不少片段深入讨论了 LSM Tree 在 LevelDB、RocksDB、HBase 的实现方式。
- 写入先到内存中的 MemTable(跳跃表或红黑树)形成有序块;
- 磁盘文件按层组织,定期合并(Compaction);
- 读取要查多层,但通过布隆过滤器减少无畏 IO。
这是“读写放大”的复杂平衡:用顺序写+分批合并压低磁盘 IO。相比 B+ 树,LSM 更适合高写入吞吐、写比读重的场景。B+ 树仍然用于 PostgreSQL、MySQL 的 InnoDB 等传统引擎,因为读的延迟低且稳定。
10. 基于位级别的结构:位图索引、Roaring Bitmap
评论针对许多大规模用户画像、广告投放系统提到 Roaring Bitmap 的价值。整型集合若用普通数组消耗大、用 bit 向量太密集(若集合稀疏)。Roaring 的聪明之处在于自动选择容器:当数据稀疏用「数组容器」(高16位分裂容器),数据密集才切换成「位图容器」,并将大集合拆分成多个 65536 大小的 chunk。
由此,它在时间和空间的平衡极佳,被 Apache Druid、Spark 内部索引作为默认选择。这种“自适应容器格式”的思路值得学习:数据结构不固定为单一形态,而是根据负载语义自适应切换。
11. 有趣的串行化检索:Wavelet Tree(小波树)
小波树经常出现在字符串处理、全文检索、压缩数据结构的课程里,但在实际工程里少见。它能在压缩文本序列上快速执行 range count,rank, select 操作,适合对大规模文本进行高效的统计查询而无需解压。
评论区有人拿它来对大段 DNA 序列做支持 rank 的长字符串检索,实验可行性很高,是“被学术低估、但实际很好用”的代表性例子。
12. 概率数据结构家族:HyperLogLog, Count-Min Sketch, SimHash
这些统计类数据结构是互联网公司运营保障的基石。
- HyperLogLog:用在 Redis 中统计巨大集合的基数(例如页面 UV),用极小的空间,误差控制很好。
- Count-Min Sketch:近似统计频率分布,用于查找热门关键词、Top-K。
- SimHash:文本片段哈希+加权位运算,让相似内容获得近似的哈希值,适合去重、同源检测。
讨论倾向于是用它们快速完成 90%近似,同时在最后阶段用精确算法兜底,实现又快又不错的实时统计。
总结:数据结构的选择本质是平衡艺术
评论中高赞的回答指出:现代工程中使用高效数据结构,本质上要面对性能与扩展性,同时牢记现实条件的约束——内存布局、分配器行为、内存页错误成本、并发竞争机制、数据局部性、动态静态差别。
最优雅的结构不一定实用,最实用的结构往往有内在取舍,因此优秀数据结构的审美在于“简洁与场景的匹配”。不少人也在对比“理论最优”与“工程最优”:Fibonacci Heap 理论最优,但 Pairing Heap 实践更好;B+ 树理论不突出,却长期统治数据库无热键索引;LSM 牺牲读性能,却换来写吞吐巅峰。
参考链接
原文:https://news.ycombinator.com/item?id=32186203
(本文综合了该讨论帖的积累观点与常见工程实践,并非逐句翻译,而是整理为一份面向中文技术社区的结构化笔记。)