什么是鲜为人知但有用的数据结构?

时间:2009-02-01 11:12:25

标签: language-agnostic data-structures computer-science

有些数据结构非常有用,但大多数程序员都不知道。他们是哪一个?

每个人都知道链接列表,二叉树和哈希,但是例如Skip listsBloom filters。我想知道更多不常见的数据结构,但值得了解,因为它们依赖于伟大的想法并丰富了程序员的工具箱。

PS:我也对像Dancing links这样的技术感兴趣,这些技术巧妙地使用了公共数据结构的属性。

修改: 请尝试包含链接以更详细地描述数据结构的页面。另外,尝试在为什么数据结构很酷的情况下添加几个单词(如Jonas Kölker已经指出的那样)。另外,尝试为每个答案提供 一个数据结构 。这将允许更好的数据结构根据他们的投票单独浮动到顶部。

83 个答案:

答案 0 :(得分:271)

Tries,也称为前缀树或crit-bit trees,已经存在了40多年,但仍然相对不为人知。 “TRASH - A dynamic LC-trie and hash data structure”中描述了一种非常酷的try尝试,它将trie与散列函数结合起来。

答案 1 :(得分:231)

Bloom filter m 位的位数组,最初都设置为0.

要添加项目,请通过 k 哈希函数运行它,该函数将为您提供数组中的 k 索引,然后将其设置为1.

要检查项目是否在集合中,请计算 k 索引并检查它们是否都设置为1.

当然,这给出了一些假阳性的可能性(根据维基百科它约为0.61 ^(m / n),其中n是插入项目的数量)。假阴性是不可能的。

删除项目是不可能的,但您可以实现计算布隆过滤器,由整数数组和递增/递减表示。

答案 2 :(得分:140)

Rope:这是一个字符串,允许廉价的prepends,子串,中间插入和追加。我真的只使用过一次,但没有其他结构就足够了。常规字符串和数组前置对于我们需要做的事情来说太昂贵了,并且逆转翻转是不可能的。

答案 3 :(得分:128)

Skip lists非常整洁。

  

Wikipedia
  跳过列表是一种概率数据结构,基于多个并行排序链表,效率可与二叉搜索树相媲美(订单日志n大多数操作的平均时间)。

它们可以用作平衡树的替代品(使用probalistic平衡而不是严格执行平衡)。它们易于实施,并且比红黑树更快。我认为他们应该在每个优秀的程序员工具中。

如果你想深入介绍跳过列表,请参阅麻省理工学院的算法导论课程link to a video

此外,here是一个Java applet,可以直观地展示Skip Lists。

答案 4 :(得分:92)

Spatial Indices,特别是R-treesKD-trees,可以有效地存储空间数据。它们适用于地理地图坐标数据和VLSI布局布线算法,有时也适用于最近邻搜索。

Bit Arrays可以紧凑地存储单个位,并允许快速位操作。

答案 5 :(得分:87)

Zippers - 数据结构的衍生物,修改结构以具有“光标”的自然概念 - 当前位置。这些非常有用,因为它们可以保证指标不受限制 - 使用,例如在xmonad window manager中跟踪哪个窗口已经聚焦。

令人惊讶的是,您可以通过applying techniques from calculus将它们推导出原始数据结构的类型!

答案 6 :(得分:69)

以下是一些:

  • 后缀尝试。几乎适用于所有类型的字符串搜索( http://en.wikipedia.org/wiki/Suffix_trie#Functionality)。另见后缀数组;它们不如后缀树快,但要小得多。

  • 播放树木(如上所述)。他们很酷的原因有三个:

    • 它们很小:你只需要像在任何二叉树中那样使用左右指针(不需要存储节点颜色或大小信息)
    • 它们(相对)非常容易实现
    • 它们为一系列“测量标准”提供了最佳的摊销复杂性(log n查找时间是每个人都知道的)。请参阅 http://en.wikipedia.org/wiki/Splay_tree#Performance_theorems
  • 按顺序排列的搜索树:您在树中存储了一堆(key,prio)对,这样它就是一个关于键的搜索树,并根据优先级进行堆排序。可以证明这样的树具有独特的形状(并且它并不总是完全包装在左上方)。通过随机优先级,它可以为您提供预期的O(log n)搜索时间,IIRC。

  • 利基是具有O(1)个邻居查询的无向平面图的邻接列表。这不是一种数据结构,而是组织现有数据结构的特定方式。以下是您的操作方法:每个平面图都有一个度数最多的节点6.选择这样一个节点,将其邻居放在其邻居列表中,将其从图中删除,然后递归直到图表为空。当给出一对(u,v)时,在v的邻居列表中查找u,在u的邻居列表中查找v。两者的大小最多为6,所以这是O(1)。

通过上面的算法,如果u和v是邻居,你将不会同时拥有v列表中的u和你列表中的v。如果需要,只需将每个节点的缺失邻居添加到该节点的邻居列表中,但存储需要查看多少邻居列表才能快速查找。

答案 7 :(得分:65)

我认为标准数据结构的无锁替代方案,即无锁队列,堆栈和列表都被忽视了 它们越来越相关,因为并发性变得更高优先级,并且比使用互斥锁或锁来处理并发读/写更加令人钦佩。

这是一些链接
http://www.cl.cam.ac.uk/research/srg/netos/lock-free/
http://www.research.ibm.com/people/m/michael/podc-1996.pdf [PDF链接]
http://www.boyet.com/Articles/LockfreeStack.html

Mike Acton's(通常具有挑衅性)博客有一些关于无锁设计和方法的优秀文章

答案 8 :(得分:55)

我认为Disjoint Set非常适合需要将一堆项目划分为不同的集合和查询成员资格的情况。 Union和Find操作的良好实现导致有效的常量摊销成本(如果我正确地回忆起我的数据结构类,则与Ackermnan函数相反)。

答案 9 :(得分:52)

Fibonacci heaps

它们被用于一些最快的已知算法(渐近地)用于许多与图形相关的问题,例如最短路径问题。 Dijkstra算法在标准二进制堆的O(E log V)时间内运行;使用Fibonacci堆可以将其提高到O(E + V log V),这对于密集图来说是一个巨大的加速。不幸的是,它们具有很高的常数因子,通常使它们在实践中变得不切实际。

答案 10 :(得分:44)

任何具有3D渲染经验的人都应该熟悉BSP trees。一般来说,这是通过将3D场景结构化为可管理来了解相机坐标和方位的方法。

  

二进制空间分区(BSP)是一个   用于递归细分的方法   通过超平面进入凸集的空间。   这种细分产生了一个   通过手段表示场景   被称为a的树数据结构   BSP树。

     

换句话说,它是一种方法   打破错综复杂的形状   多边形成凸集,或更小   完全由多边形组成的多边形   非反射角(角度小于   180°)。有关更一般的说明   空间划分,看空间   分区。

     

最初,提出了这种方法   在3D计算机图形学中增加   渲染效率。其他   应用包括表演   具有形状的几何操作   CAD中的(构造实体几何)   机器人和3D中的碰撞检测   电脑游戏等电脑   涉及处理的应用程序   复杂的空间场景。

答案 11 :(得分:43)

Huffman trees - 用于压缩。

答案 12 :(得分:38)

查看Finger Trees,特别是如果您是previously mentioned纯功能数据结构的粉丝。它们是持久性序列的功能表示,支持以摊销的恒定时间访问末端,并且在较小的片段的大小中以时间对数进行连接和分割。

根据the original article

  

我们的功能性2-3指树是由Okasaki(1998)引入的一般设计技术的实例,称为隐式递归减速。我们已经注意到这些树是其隐式deque结构的扩展,用2-3个节点替换对,以提供有效连接和拆分所需的灵活性。

手指树可以使用monoid进行参数化,并且使用不同的幺半群将导致树的不同行为。这使得Finger Trees可以模拟其他数据结构。

答案 13 :(得分:34)

Circular or ring buffer - 用于流式传输等。

答案 14 :(得分:33)

我很惊讶没有人提到Merkle树(即Hash Trees)。

在许多情况下(P2P程序,数字签名)使用,当您只有部分文件可用时,您要验证整个文件的哈希值。

答案 15 :(得分:32)

  

< zvrba> Van Emde-Boas树

我认为知道为什么他们很酷很有用。一般来说,问题“为什么”是最重要的问题;)

我的回答是他们为你提供了带有{1..n}键的O(log log n)字典,与使用的密钥数量无关。就像重复减半给你O(log n)一样,重复的sqrting给你O(log log n),这就是vEB树中发生的事情。

答案 16 :(得分:31)

splay trees怎么样?

此外,克里斯·冈崎的purely functional data structures浮现在脑海中。

答案 17 :(得分:29)

哈希表的有趣变体称为Cuckoo Hashing。它使用多个哈希函数而不是1来处理哈希冲突。通过从主哈希指定的位置删除旧对象,并将其移动到备用哈希函数指定的位置来解决冲突。 Cuckoo Hashing允许更有效地使用内存空间,因为只需3个哈希函数就可以将加载因子提高到91%,而且访问时间仍然很长。

答案 18 :(得分:27)

min-max heap是实现双端优先级队列的heap的变体。它通过对堆属性的简单更改来实现这一点:如果偶数(奇数)级别上的每个元素都小于(大于)所有子级和大型子级,则称树为最小 - 最大级别。级别从1开始编号。

http://internet512.chonbuk.ac.kr/datastructure/heap/img/heap8.jpg

答案 19 :(得分:26)

我喜欢Cache Oblivious datastructures。基本思想是以递归较小的块布置树,以便许多不同大小的缓存将利用方便地适合它们的块。这样可以有效地使用缓存,从RAM中的L1缓存到从磁盘读取的大块数据,而无需了解任何缓存层大小的细节。

答案 20 :(得分:23)

Left Leaning Red-Black Trees。 Robert Sedgewick于2008年发布了一个非常简化的红黑树实现(大约一半的代码行实现)。如果您在实施红黑树时遇到麻烦,请阅读此变体。

与Andersson Trees非常相似(如果不相同)。

答案 21 :(得分:22)

工作窃取队列

无锁数据结构,用于在多个线程之间平均分配工作 Implementation of a work stealing queue in C/C++?

答案 22 :(得分:19)

GerthStøltingBrodal和Chris Okasaki的

Bootstrapped skew-binomial heaps

尽管名称很长,但它们提供渐近最优的堆操作,即使在函数设置中也是如此。

  • O(1)尺寸,工会,插入,最小
  • O(log n) deleteMin

请注意,联合需要O(1)而不是O(log n)时间,而不像数据结构教科书中常见的堆,例如leftist heaps。与Fibonacci heaps不同,这些渐近线是最坏情况,而不是摊销,即使持续使用也是如此!

Haskell中有multiple implementations

在布罗达尔提出imperative heap同样的渐近线之后,他们是由布罗达尔和冈崎共同衍生出来的。

答案 23 :(得分:18)

球树。只是因为他们让人们傻笑。

球树是一种对度量空间中的点进行索引的数据结构。 Here's an article on building them.它们通常用于寻找一个点的最近邻居或加速k-means。

答案 24 :(得分:18)

  • Kd-Trees,在实时光线追踪中使用的空间数据结构(以及其他)具有以下缺点:需要剪切与不同空间交叉的三角形。通常BVH更快,因为它们更轻便。
  • MX-CIF Quadtrees,通过在四边形边缘组合常规四叉树和二叉树来存储边界框而不是任意点集。
  • HAMT,由于涉及的常数,访问时间通常超过O(1)哈希映射的分层哈希映射。
  • Inverted Index,在搜索引擎圈子中非常有名,因为它用于快速检索与不同搜索词相关联的文档。

NIST Dictionary of Algorithms and Data Structures

中记录了大部分(如果不是全部)这些内容

答案 25 :(得分:17)

不是真正的数据结构;更多优化动态分配数组的方法,但Emacs中使用的gap buffers很酷。

答案 26 :(得分:16)

芬威克树。它是一个数据结构,用于在两个给定的子索引i和j之间保持向量中所有元素之和的计数。自开始以来预先计算总和的微不足道的解决方案不允许更新项目(你必须做O(n)工作才能跟上)。

Fenwick Trees允许您在O(log n)中更新和查询,它的工作原理非常酷而且简单。在Fenwick的原始论文中可以很好地解释它,可以在这里免费获得:

http://www.cs.ubc.ca/local/reading/proceedings/spe91-95/spe/vol24/issue3/spe884.pdf

它的父亲,RQM树也非常酷:它允许你保存关于向量的两个索引之间的最小元素的信息,它也适用于O(log n)更新和查询。我喜欢先教RQM然后教Fenwick树。

答案 27 :(得分:14)

Van Emde-Boas trees。我甚至有一个C ++ implementation,最多2 ^ 20个整数。

答案 28 :(得分:13)

Nested sets非常适合在关系数据库中表示树并在它们上运行查询。例如,ActiveRecord(Ruby on Rails的默认ORM)带有一个非常简单的nested set plugin,这使得使用树很简单。

答案 29 :(得分:12)

它非常适合特定领域,但half-edge data structure非常简洁。它提供了一种迭代多边形网格(面边)的方法,这在计算机图形和计算几何中非常有用。

答案 30 :(得分:12)

替罪羊树。普通二叉树的一个典型问题是它们变得不平衡(例如当按升序插入键时)。

平衡二叉树(AKA AVL树)在每次插入后都会浪费大量时间进行平衡。

红黑树保持平衡,但每个节点需要额外的存储空间。

替罪羊树像红黑树一样保持平衡,但不需要任何额外的存储空间。他们通过在每次插入后分析树并进行微调来完成此操作。请参阅http://en.wikipedia.org/wiki/Scapegoat_tree

答案 31 :(得分:12)

unrolled linked list是链表上的变体,它在每个节点中存储多个元素。它可以显着提高缓存性能,同时减少与存储列表元数据(如引用)相关的内存开销。它与B树有关。

record node {
    node next       // reference to next node in list
    int numElements // number of elements in this node, up to maxElements
    array elements  // an array of numElements elements, with space allocated for maxElements elements
}

答案 32 :(得分:11)

2-3 Finger Trees Hinze and Paterson是一个伟大的功能数据结构瑞士军刀,具有适用于各种操作的极大渐近线。虽然复杂,但它们比卡普兰和塔尔詹之前的Persistent lists with catenation via recursive slow-down命令式结构简单得多。

它们作为可连接的双端队列,O(1)访问任一端O(log min(n,m))追加,并提供O(log min(n,length - n))索引,可直接访问序列任何部分的monoidal前缀和。

HaskellCoqF#ScalaJavaCClojure,{{ 3}}和其他语言。

您可以使用它们来实施C#priority search queuesinterval maps,地图,集合,ropes with fast head access或几乎任何可以将其标记为收集{的结构{3}}导致快速连接/可索引序列。

我还有一些catenable sequences描述了它们的推导和使用。

答案 33 :(得分:10)

Pairing heaps是一种堆数据结构,具有相对简单的实现和出色的实用摊销性能。

答案 34 :(得分:10)

一个鲜为人知但非常漂亮的数据结构是Fenwick Tree(有时也称为Binary Indexed Tree或BIT)。它存储累积总和并支持O(log(n))操作。虽然累积总和可能听起来不太令人兴奋,但它可以适用于解决需要排序/日志(n)数据结构的许多问题。

国际海事组织,其主要卖点是implemented的轻松程度。在解决算法问题时非常有用,否则会涉及编码红黑/ avl树。

答案 35 :(得分:10)

XOR Linked List使用两个XOR'd指针来减少双向链表的存储要求。有点晦涩而又整洁!

答案 36 :(得分:10)

我真的很喜欢Interval Trees。它们允许您采用一系列间隔(即开始/结束时间或其他)并查询哪些时间间隔包含给定时间,或者在给定时间段内哪些时间间隔为“活动”。查询可以在O(log n)中完成,预处理是O(n log n)。

答案 37 :(得分:9)

Splash Tables很棒。它们就像一个普通的哈希表,除了它们保证了恒定时间查找,并且可以在不损失性能的情况下处理90%的利用率。它们是Cuckoo Hash(也是一个很好的数据结构)的概括。它们似乎确实是patented,但与大多数纯软件专利一样,我不会太担心。

答案 38 :(得分:8)

地区四叉树

(引自Wikipedia

  

区域四叉树通过将区域分解为四个相等的象限,子等分数等来表示二维空间的划分,其中每个叶节点包含对应于特定子区域的数据。树中的每个节点都有四个子节点,或者没有子节点(叶子节点)。

像这样的四叉树有利于存储空间数据,例如纬度和经度或其他类型的坐标。

这是迄今为止我最喜欢的大学数据结构。编码这个人并看到它的工作非常酷。如果你正在寻找一个需要思考的项目,并且有点偏离常规,我强烈推荐它。无论如何,它比你通常在数据结构类中分配的标准BST衍生物更有趣!

事实上,作为奖励,我发现了讲座的笔记,这些笔记通向了班级项目(来自弗吉尼亚理工大学)here (pdf warning)

答案 39 :(得分:8)

增强的散列算法非常有趣。 Linear hashing很简洁,因为它允许一次在哈希表中拆分一个“桶”,而不是重新整理整个表。这对分布式缓存特别有用。但是,通过大多数简单的拆分策略,您最终会快速连续拆分所有存储桶,并且表的负载因子振荡得非常糟糕。

我认为spiral hashing真的很整洁。与线性散列一样,一次分割一个桶,并将桶中少于一半的记录放入同一个新桶中。它非常干净,快速。但是,如果每个“桶”由具有类似规格的机器托管,则效率可能会很低。要充分利用硬件,您需要混合使用功能较少且功能更强大的机器。

答案 40 :(得分:8)

Binary decision diagram是我最喜欢的数据结构之一,或者实际上是降阶有序二进制决策图(ROBDD)。

这种结构可以用于:

  • 表示项目集并对这些集合执行非常快速的逻辑操作。
  • 任何布尔表达式,旨在查找表达式的所有解决方案

请注意,许多问题可以表示为布尔表达式。例如,suduku的解决方案可以表示为布尔表达式。为该布尔表达式构建BDD将立即产生解决方案。

答案 41 :(得分:7)

我喜欢treaps - 为了平衡它而在叠加搜索树上叠加具有随机优先级的堆结构的简单而有效的想法。

答案 42 :(得分:6)

Arne Andersson trees是红黑树的简单替代方案,其中只有正确的链接可以是红色。这大大简化了维护,同时保持性能与红黑树相当。原始论文提供了nice and short implementation的插入和删除。

答案 43 :(得分:6)

计算未分类的平衡btree。

适合文本编辑器缓冲区。

http://www.chiark.greenend.org.uk/~sgtatham/algorithms/cbtree.html

答案 44 :(得分:6)

我有时使用 Inversion LIsts 来存储范围,它们通常用于在正则表达式中存储字符类。请参阅示例http://www.ibm.com/developerworks/linux/library/l-cpinv.html

另一个不错的用例是加权随机决策。假设您有一个符号列表和相关概率,并且您希望根据这些概率随机选择它们

   a => 0.1
   b => 0.5
   c => 0.4

然后你对所有概率进行总和:

  (0.1, 0.6, 1.0)

这是您的反转列表。您生成一个介于0和1之间的随机数,并查找列表中下一个更高条目的索引。您可以使用二进制搜索来执行此操作,因为它已经过排序。获得索引后,您可以在原始列表中查找符号。

如果你有n个符号,你有O(n)个准备时间,然后是每个随机选择的符号的O(log(n))访问时间 - 与权重的分布无关。

反转列表的变体使用负数来表示范围的终点,这使得可以很容易地计算在某个点重叠的范围。有关示例,请参阅http://www.perlmonks.org/index.pl?node_id=841368

答案 45 :(得分:6)

Fast Compact尝试:

答案 46 :(得分:6)

DAWG是一种特殊的Trie,类似的子树被压缩成单亲。我扩展了修改后的DAWG,并提出了一个名为ASSDAWG(Anagram Search Sorted DAWG)的漂亮数据结构。这种方式的工作方式是每当一个字符串插入DAWG时,它首先进行桶式排序然后插入,叶子节点保持additional number,指示如果我们从根到达该叶子节点,哪些排列是有效的。 这有两个很好的优点:

  1. 由于我在插入之前对字符串进行排序,并且因为DAWG自然地崩溃了类似的子树,所以我获得了高水平的压缩(例如“吃”,“吃”,“茶”都变成了1路径的aet,其中包含一个数字列表叶节点指示aet的哪些排列有效。
  2. 现在搜索给定字符串的字谜是非常快速和微不足道的,因为从root到leaf的路径使用置换数字保存叶子节点上该路径的所有有效字谜。

答案 47 :(得分:5)

Zobrist Hashing是一个哈希函数,通常用于表示游戏板位置(如国际象棋),但肯定还有其他用途。关于它的一个好处是可以在更新电路板时逐步更新。

答案 48 :(得分:5)

Fenwick trees(或二进制索引树)是一个值得添加的工具包。如果你有一个计数器阵列,你需要在查询累积计数时不断更新它们(如在PPM压缩中),Fenwick树将在O(log n)时间内完成所有操作,并且不需要额外的空间。另请参阅此topcoder tutorial以获得详细介绍。

答案 49 :(得分:5)

我喜欢suffix treearrays进行字符串处理,skip lists表示平衡列表,splay trees表示自动平衡树

答案 50 :(得分:5)

答案 51 :(得分:5)

BK-Trees, or Burkhard-Keller Trees是一个基于树的数据结构,可用于快速查找字符串的近匹配。

答案 52 :(得分:4)

Splay树很酷。它们以一种将最常查询的元素移动到根部的方式重新排序。

答案 53 :(得分:4)

答案 54 :(得分:4)

远离所有这些图形结构,我只喜欢简单的 Ring-Buffer

如果正确实施,您可以在保持性能的同时严重减少内存占用,有时甚至可以进行改进。

答案 55 :(得分:4)

根据Bloom Filter提及,可删除布隆过滤器(DlBF)在某些方面优于基本计数变体。见http://arxiv.org/abs/1005.0352

答案 56 :(得分:4)

您可以使用min-heap在常量时间中查找最小元素,或使用max-heap查找最大元素。但是如果你想做两个操作呢?您可以使用Min-Max在固定时间内执行这两项操作。它使用最小最大排序:在连续树级别之间的最小和最大堆比较之间交替。

答案 57 :(得分:4)

B* tree

这是一种各种B树,它可以以更昂贵的插入成本进行搜索。

答案 58 :(得分:3)

跳过列表实际上非常棒:      http://en.wikipedia.org/wiki/Skip_list

答案 59 :(得分:3)

使用2个堆栈实现的队列非常节省空间(与使用至少有1个额外指针/引用开销的链表相反)。

How to implement a queue using two stacks?

当队列庞大时,这对我来说效果很好。如果我在指针上保存8个字节,则意味着具有一百万个条目的队列可以节省大约8MB的RAM。

答案 60 :(得分:3)

Ternary Search Tree

  • 快速前缀搜索(用于增量自动完成等)
  • 部分匹配(当您想要查找字符串的X汉明距离内的所有单词时)
  • 通配符搜索

非常容易实施。

答案 61 :(得分:3)

我认为Paolo Ferragina和Giovanni Manzini的FM-index非常酷。特别是在生物信息学方面。它本质上是一个压缩的全文索引,它使用后缀数组和参考文本的burrows-wheeler变换的组合。可以在不解压缩整个索引的情况下搜索索引。

答案 62 :(得分:3)

答案 63 :(得分:2)

PATRICIA - 用于检索字母数字编码信息的实用算法,D.R.Morrison(1968)。

PATRICIA树与Trie相关。 Tries的问题在于,当密钥集稀疏时,即当实际密钥形成潜在密钥集的一小部分时(通常情况下),Trie中的许多(大多数)内部节点仅具有一个后代。这导致Trie具有很高的空间复杂度。

http://www.csse.monash.edu.au/~lloyd/tildeAlgDS/Tree/PATRICIA/

答案 64 :(得分:2)

Disjoint Set Forests允许快速成员资格查询和联合操作,最常用于Kruskal's Algorithm最小生成树。

非常酷的是,两个操作的摊铺运行时间与Ackermann Function成正比,使其成为“最快”的非恒定时间数据结构。

答案 65 :(得分:2)

我不确定这个数据结构是否有名称,但建议的tokenmap数据结构包含在Boost中是有趣的。它是一个动态可调整大小的映射,其中查找不仅是O(1),它们是简单的数组访问。我在这个数据结构上写了大部分background material,描述了它的工作原理背后的基本原理。

操作系统使用类似于tokenmap的东西将文件或资源句柄映射到表示文件或资源的数据结构。

答案 66 :(得分:2)

在cron或事件模拟器等程序中使用增量列表/增量队列来计算下一个事件应该触发的时间。 http://everything2.com/title/delta+list http://www.cs.iastate.edu/~cs554/lec_notes/delta_clock.pdf

答案 67 :(得分:2)

Burrows–Wheeler transform(块排序压缩)

其压缩的基本算法。假设您要压缩文本文件上的行。你会说,如果你排序,你就会丢失信息。但是BWT的工作方式是这样的 - 它通过对输入进行排序来减少熵,保持整数索引以恢复原始顺序。

答案 68 :(得分:2)

A corner-stitched data structure。摘要摘要:

  

角拼接是一种技巧   代表矩形   二维物体。它似乎   特别适合   VLSI的交互式编辑系统   布局。数据结构有两个   重要特征:第一,空的空间   明确表示;第二,   矩形区域缝合   在他们的角落一起像一个   拼凑被子。这个组织   导致快速算法(线性   时间或更好)搜索,   创作,删除,拉伸和   压实。算法是   以简化模型呈现   VLSI电路和存储器   结构的要求是   讨论。测量表明   角拼接需要   大约是其三倍   内存空间是最简单的   表示。

答案 69 :(得分:2)

Bucket Brigade

它们在Apache中广泛使用。基本上它们是一个链接列表,它在一个环中自行循环。我不确定它们是否在Apache和Apache模块之外使用,但它们适合作为一种很酷但鲜为人知的数据结构。存储桶是一些任意数据的容器,存储桶旅是存储桶的集合。我们的想法是,您希望能够在结构中的任何位置修改和插入数据。

假设您有一个包含一个html文档的存储桶文件,每个存储桶包含一个字符。您希望将所有<>符号转换为&lt;&gt;个实体。当你遇到<>符号时,桶旅允许你在旅中插入一些额外的桶,以适应实体所需的额外字符。由于铲斗旅在一个环中,您可以向后或向前插入。这比使用简单缓冲区更容易(在C中)。

以下关于桶旅的一些参考:

Apache Bucket Brigade Reference

Introduction to Buckets and Brigades

答案 70 :(得分:2)

我个人觉得稀疏矩阵数据结构非常有趣。 http://www.netlib.org/linalg/html_templates/node90.html

着名的BLAS图书馆使用这些。当您处理包含100,000行和列的线性系统时,使用它们变得至关重要。其中一些也类似于紧凑的网格(基本上像铲斗分类网格),这在计算机图形学中很常见。 http://www.cs.kuleuven.be/~ares/publications/LD08CFRGRT/LD08CFRGRT.pdf

就计算机图形而言,MAC网格有点有趣,但仅仅因为它们很聪明。 http://www.seas.upenn.edu/~cis665/projects/Liquation_665_Report.pdf

答案 71 :(得分:2)

答案 72 :(得分:2)

正确的字符串数据结构。几乎每个程序员都会支持语言对结构的本地支持,而且效率通常很低(特别是对于构建字符串,你需要一个单独的类或其他东西)。

最糟糕的是将字符串视为C中的字符数组,并依赖于NULL字节以确保安全。

答案 73 :(得分:1)

之前我曾与WPL Trees好运。树变体,最小化分支的加权路径长度。权重由节点访问确定,以便频繁访问的节点更靠近根迁移。不知道它们与splay树相比如何,因为我从未使用过它们。

答案 74 :(得分:1)

其他人已经提出了Burkhard-Keller-Trees,但我想我可能会再次提及它们以插入我自己的实现。 :)

http://well-adjusted.de/mspace.py/index.html

有更快的实现(参见ActiveState的Python配方或其他语言的实现),但我认为/希望我的代码有助于理解这些数据结构。

顺便说一句,BK和VP树都可以用于搜索类似的字符串。只要您具有满足一些条件(积极性,对称性,三角不等式)的距离函数,就可以对任意对象进行相似性搜索。

答案 75 :(得分:1)

Half edge data structurewinged edge用于多边形网格。

对计算几何算法很有用。

答案 76 :(得分:1)

有一个聪明的数据结构,它使用数组来保存元素的数据,但是数组在链接列表/数组中链接在一起。

这确实具有以下优点:对元素的迭代非常快(比纯链接列表方法更快)并且在内存和/或(解)分配中移动具有元素的数组的成本是至少。 (因此,这种数据结构对于模拟东西很有用)。

我从这里知道:

http://software.intel.com/en-us/blogs/2010/03/26/linked-list-verses-array/

“......并且分配了一个额外的数组并将其链接到粒子数组的单元格列表中。这在某些方面类似于TBB实现其并发容器的方式。”(这是关于链接列表的性能)与数组相比)

答案 77 :(得分:1)

环境跟踪递归结构。

编译器使用递归但不像树的结构。内部范围具有指向封闭范围的指针,因此嵌套是由内向外的。验证变量是否在范围内是从内部范围到封闭范围的递归调用。

public class Env
{    
    HashMap<String, Object> map;
    Env                     outer;

    Env()
    {
        outer = null;
        map = new HashMap();
    }

    Env(Env o)
    {
        outer = o;
        map = new HashMap();
    }

    void put(String key, Object value)
    {
        map.put(key, value);
    }

    Object get(String key)
    {
        if (map.containsKey(key))
        {
            return map.get(key);
        }
        if (outer != null)
        {
            return outer.get(key);
        }
        return null;
    }

    Env push()
    {
        return new Env(this);
    }

    Env pop()
    {
        return outer;
    }
}

我不确定这个结构是否有名字。我将其称为内向外列表。

答案 78 :(得分:1)

我认为Cycle Sort是一个非常整洁的排序算法。

这是一种用于最小化写入总数的排序算法。当您处理闪存的寿命与写入量成比例时,这尤其有用。这是Wikipedia article,但我建议转到第一个链接。 (不错的视觉效果!)

答案 79 :(得分:1)

Binomial heap有很多有趣的属性,其中最有用的是合并。

答案 80 :(得分:1)

  • 二进制决策图(我非常喜欢的数据结构,适用于表示布尔方程,并解决它们。对很多事情都有效)
  • 堆(节点的父节点始终与节点的子节点保持某种关系的树,例如,节点的父节点总是大于它的每个子节点(最大堆))
  • 优先级队列(实际上只是最小堆和最大堆,有利于维护那里的许多元素的顺序,例如,应该首先删除具有最高值的项目)
  • 哈希表,(具有各种查找策略和存储桶溢出处理)
  • 平衡二叉搜索树(每个都有自己的优势)
    • RB-trees(总体来说,当以有序的方式插入,查找,删除和迭代时)
    • Avl-trees(查找速度比RB快,但与RB非常相似)
    • 播放树(当最近使用的节点可能被重用时查找速度更快)
    • Fusion-tree(利用快速乘法来获得更好的查找时间)
    • B + Trees(用于数据库和文件系统中的索引,当从/向索引读取/写入的延迟很大时非常有效)。
  • 空间索引(非常适合查询点/圆/矩形/线/立方体是否彼此靠近或包含在内)
    • BSP树
    • 四叉树
    • 八叉树
    • 范围树
    • 许多相似但略有不同的树木和不同的尺寸
  • 区间树(很好找到重叠区间,线性)
  • 图表
    • 邻接列表(基本上是边缘列表)
    • 邻接矩阵(表示每个边缘具有单个位的图的有向边的表。图遍历非常快)

这些是我能想到的。关于data structures

,维基百科上还有更多内容

答案 81 :(得分:0)

Right-angle triangle networks (RTINs)

自适应细分网格的简单方法。拆分和合并操作只是几行代码。

答案 82 :(得分:0)

当我读到与RMQ和LCA相关的一些算法时,我偶然发现了另一个数据结构Cartesian Tree。在笛卡尔树中,两个节点之间的最低共同祖先是它们之间的最小节点。将RMQ问题转换为LCA非常有用。