这实际上取决于您对“最近”的定义。 CLRS 包含大量数据结构,但就其本质而言,它无法涵盖多年来开发的所有伟大思想和技术。以下是研究领域的样本以及来自那里的一些结果:
二叉搜索树
在“经典”方面,最近开发的 WAVL 树是一种简单的平衡树结构,在仅插入的情况下其行为类似于 AVL 树(紧密平衡),并且当插入和删除混合时,它的表现永远不会比红/黑树。还有zip tree,这是一种将概率跳跃列表编码为二叉搜索树的方法,并且有一组非常简单的规则。
Splay trees 是第一个通过在查找过程中重新排列节点来实现出色性能的二叉搜索树。它们具有许多优良的理论性质。尽管从 1980 年代首次开发的意义上说,它们并不是“现代”的,但它们开启了一个新的研究领域:探索是否存在单一的二叉搜索树,在某种意义上,它是“最好的” " 可能的二叉搜索树。这样的树在理想情况下会提供 O(log n) 查找,但还具有其他理想的属性,例如“查找最近搜索过的项目所需的时间更少”和“查找最近查询的项目附近的项目应该快点。”在 2000 年代,我们看到了 tango 树 和 multisplay 树 的发展,它们具有不同寻常的保证,即在这些树上执行一系列操作的成本永远不会更高比在 any 二叉搜索树上执行这些操作慢 O(log log n) 倍。
在 2010 年代初期,研究人员发现二叉搜索树算法与 2D 平面中的点集之间存在联系。这种“二叉搜索树的几何”已被用于寻找 BST 结构的新下界,并产生了 BST 的新候选者,对于“尽可能好”的某些定义,它可能“尽可能好”。 "
其他需要检查的平衡树和树状结构包括 1990 年代开发的跳过列表、treap 和替罪羊树。
素描和采样
许多最近的数据结构设计用于处理数据流,其中项目一次只能看到一个元素。目标是计算有关数据流的统计信息,同时使用远低于存储所有元素所需的空间。 (想想谷歌跟踪流行的搜索查询或推特寻找趋势标签 - 有太多东西同时进入实时跟踪所有发布的内容)。 count-min sketch 可以估计各种项目在数据流中出现的频率,并可用于查找在流中频繁出现的项目。 HyperLogLog 估计器 使用很小的空间,并且可以估计已经看到了多少不同的项目。像 AMS 估计器这样的估计器可以用来估计数据分布的偏斜程度。
内存优化结构
对缓存遗忘数据结构进行了大量研究。缓存忽略结构背后的想法是计算机中的内存通常涉及多层缓存,并且基于这些缓存的大小调整数据结构已经有一段时间了,以提供性能提升(参见,例如, B树)。在缓存忽略模型中,数据结构需要充分利用缓存,但不知道缓存大小。令人惊讶的是,这是可能的,我们有满足这个目标的二叉搜索树和优先级队列。
哈希表
Cuckoo 哈希是在 2000 年代初开发的,它提供了一种构建哈希表的方法,其中查找需要 worst-case 时间 O(1)。他们在实践中很快,他们的分析导致了对随机超图属性的研究。
线性探测自 1960 年代以来就在假设随机散列函数的情况下表现良好,但正式表明需要 5 个独立散列函数才能在理论上快速运行。
在 2010 年代,一些 Google 工程师开发了“瑞士表”,这是一种基于线性探测的极快哈希表,它利用 SIMD 指令来进一步提升性能。
布隆过滤器替换
Bloom 过滤器自 1970 年代就已经存在,它提供了一种在少量空间中存储集合的绝佳方式,前提是误报是可以接受的。在 2000 年代、2010 年代和 2020 年代,开发了许多实用的数据结构,在实践中对其进行了改进。 d-left counting Bloom filter 支持大约 2 倍空间下降的插入和删除。较新的cuckoo filter 比传统的布隆过滤器使用更少的空间(为了合理的错误率)并支持插入和删除。在所有情况下,XOR filter 使用的空间都比布隆过滤器少,前提是预先知道要存储的项目。
XOR 过滤器与 Bloomier 过滤器 相关,后者是一种存储字典近似值的方法,类似于 Bloom 过滤器如何存储集合的近似值。它们在 2010 年代后期的一篇论文中被用于压缩具有低错误率的机器学习模型。
还开发了几种纯粹出于理论兴趣的数据结构,表明在替换布隆过滤器时可以实现理论上的最佳位数。 Porat 的矩阵过滤器可能是最简单的,而 Pagh、Pagh 和 Rao 的方法是 (IIRC) 第一个这样做的。
简洁紧凑的数据结构
编码一个数据结构需要多少位?这个问题引发了简洁紧凑的数据结构领域。使用接近信息论的最小位数来编码复杂的结构(如树)是可能的。查看 小波树 作为如何执行此操作的示例。也有人在构建使用数据压缩来减小结构大小同时保持结构有用的数据结构。 FM-index 就是一个很好的例子。
持久数据结构
持久性数据结构是一种数据结构,其中执行编辑会产生两个版本的结果 - 一个在应用编辑之前,一个在应用之后。这在 1980 年代由 Sarnak 和 Tarjan 首次探索,并导致了 2D 点定位的改进。
纯函数式数据结构是其中的一个子案例,可用于函数式语言(或用于保证持久性的命令式语言)。例如,Chris Okasaki 在该领域的工作促成了新树和优先级队列的开发。
动力学数据结构
动力学数据结构是存储移动对象的数据结构。这允许诸如“给定这组移动粒子,哪一对将是下一个碰撞?”之类的操作。并在计算机图形学中找到了应用。搜索“动力学优先级队列”以获得很好的介绍。
并发数据结构
并发数据结构是在多线程环境中运行良好的数据结构。有一些巧妙的方法可以构建哈希表和优先级队列,它们可以同时处理多个读取器和多个写入器,而无需锁定整个结构,其中许多已被 Java 的标准库采用,而其他一些可用于并发繁重的工作流.
几何数据结构
用于处理 2D、3D 和更高维空间中的点的数据结构在计算机图形和数据处理中都有应用。这里有很大的空间可以覆盖;这里有一些亮点。
point location problem 的数据结构将 2D 平面细分为多个区域,并支持“给定一个点,它位于哪个空间区域?”形式的查询。有很多方法可以解决这个问题。有些使用持久数据结构。其他基于将三角形网格细化为网格层次结构。其他人则通过将世界分割成梯形来工作。
正交范围搜索问题要求存储点集合的数据结构并回答以下形式的查询:“这个轴对齐框中的所有点是什么?”范围树和 k-d 树是在 1970 年代开发的,在实践中仍然有用。在 2020 年代继续开发的更现代的方法在理论上使用分数级联和整数数据结构的混合来改善这些运行时。
字符串数据结构
用于字符串处理的数据结构,即后缀树,与生物计算和网络搜索极为相关。我认为 CLRS 甚至没有提到它们的存在。但是,您绝对应该研究它们,因为它们负责基因组学的大部分新工作。最近在后缀数组构造算法方面有一些非常酷的发展,SA-IS 等算法弥合了理论上和实际快速算法之间的差距。
整数数据结构
许多研究人员已努力构建数据结构,以利用现代机器可以并行处理多个位这一事实。一些结构,如融合树、指数树或 y-fast 树,利用这些属性在整数数组中进行排序和搜索,比在简单比较模型中施加的 O(n lg n) 障碍更快。 fusion tree 及其后代(指数树等)表明,通过字级并行性,您可以获得一些令人印象深刻的理论加速,尽管这些结构在实践中并不是超级快。
整数数据结构也被用于为单源最短路径问题提供 O(m + n) 时间的算法,在理论上比 Dijkstra 算法更好,假设权重是整数。不过,该算法基本上只具有理论意义,因为实现它所使用的常数因子太高而无法实用。
优先队列
斐波那契堆是第一个在(摊销)时间 O(1) 内支持入队、合并和减少键的优先级队列,并在提取最小(摊销)时间 O(log n) 内支持,提高了Dijkstra 算法、Prim 算法以及其他类似 Stoer-Wagner 最小割算法。从那时起,已经开发了许多其他优先级队列来简化斐波那契堆或在最坏的情况下满足这些时间限制。 Quake heaps 是一个更简单的结构(概念上),但在实践中运行速度并不快。严格的斐波那契堆实现与斐波那契堆相同的时间界限,但在最坏的情况下。
基于展开树的配对堆在实践中比斐波那契堆快得多。最初推测它满足与斐波那契堆相同的时间界限,但在它们开发多年后证明并非如此。截至 2021 年,配对堆的实际运行时间尚不清楚。
动态图表
图上的许多经典问题(“给定两个节点,它们之间是否存在路径?”“找到最小生成树。”“检查图是否为平面”)已知快速算法。但是,如果允许图表随时间变化会发生什么?突然之间,如果不在每次编辑时从头开始重新计算所有内容,这些问题就会变得更加难以有效解决。
在底层图是森林的情况下,Euler 巡回树、st 树(有时称为链接/切割树)和顶层树可以回答许多有趣的问题,例如每次编辑的更新时间非常短的连通性。
对于一般图,Holm 等人的分层森林结构在添加或删除边时保持图中的连通性和 MST,并具有相当好的摊销运行时间。 Kapron 等人的割集结构使用随机化来执行更新,具有良好的最坏情况效率和高成功概率。
范围最小查询数
范围最小查询问题是预处理一个值数组,以便查询“这个子数组中最小的条目是什么?”形式的查询。可以快速回答。在 1980 年代,人们发现了一种使用线性预处理时间和 O(1) 查询时间的解决方案,并且多年来该解决方案已被简化和改进为在实践中运行速度非常快的解决方案(搜索“Fischer-Heun 结构”。)
RMQ 的应用数量惊人,尤其是与树(可用于快速找到最低共同祖先)以及后缀树和后缀数组(它支持许多令人印象深刻的算法)结合使用时