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

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

PS:我也对像跳舞链接这样的技巧感兴趣,这些技巧巧妙地使用了常见数据结构的属性。

编辑 :请尝试更详细地包含指向描述数据结构的页面的链接 。 此外,尝试添加几个关于数据结构为什么很酷的词(正如JonasKölker已经指出的那样)。 此外,尝试为每个答案提供一个数据结构 。 这将允许更好的数据结构根据他们的投票单独浮动到顶部。


#1楼

斐波那契堆积

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


#2楼

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

这是一些链接
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 (通常是挑衅性的)博客有一些关于无锁设计和方法的优秀文章


#3楼

我很惊讶没有人提到Merkle树(即哈希树 )。

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


#4楼

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

根据原始文章 :

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

手指树可以参数与独异 ,并使用不同的类群将导致树不同的行为。 这使得Finger Trees可以模拟其他数据结构。


#5楼

拉链 - 数据结构的衍生物,修改结构以具有“光标”的自然概念 - 当前位置。 这些非常有用,因为它们可以保证指标不会超出界限 - 例如在xmonad窗口管理器中用于跟踪哪个窗口已经聚焦。

令人惊讶的是,您可以通过将微积分技术应用于原始数据结构的类型来推导它们!


#6楼

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


#7楼

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


#8楼

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

与安德森树非常相似(如果不相同)。


#9楼

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


#10楼

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

球树是一种对度量空间中的点进行索引的数据结构。 这是一篇关于构建它们的文章。 它们通常用于寻找点的最近邻居或加速k均值。


#11楼

芬威克树。 它是一个数据结构,用于在两个给定的子索引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树。


#12楼

由GerthStøltingBroodal和Chris Okasaki 引导的扭曲二项式堆积 :

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

  • O(1)大小, 联合 ,插入,最小
  • O(log n) deleteMin

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

Haskell中有多个 实现 。

在布罗达尔提出具有相同渐近线的命令堆之后,它们是由布罗达尔和冈崎共同衍生出来的。


#13楼

工作窃取队列

用于在多个线程之间分配工作的无锁数据结构在C / C ++中实现工作窃取队列?


#14楼

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

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


#15楼

尝试 ,也称为前缀树或暴击树 ,已存在超过40年,但仍然相对未知。 在“ TRASH - 动态LC-trie和散列数据结构 ”中描述了一种非常酷的尝试用法,它将trie与散列函数结合起来。


#16楼

啪啪树怎么样?

此外,Chris Okasaki的纯功能数据结构浮现在脑海中。


#17楼

以下是一些:

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

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

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

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

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


#18楼

空间指数 ,特别是R树和KD树 ,有效地存储空间数据。 它们适用于地理地图坐标数据和VLSI布局布线算法,有时也适用于最近邻搜索。

比特串压缩存储单个位,并允许快速位操作。


#19楼

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


#20楼

<zvrba> Van Emde-Boas树木

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

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


#21楼

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

大多数(如果不是全部)这些都记录在NIST 算法和数据结构词典中


#22楼

布隆过滤器 : m位的位数组,最初都设置为0。

要添加一个项目,您可以通过k哈希函数运行它,这将在数组中为您提供k个索引,然后将其设置为1。

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

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

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


#23楼

我喜欢Cache Oblivious数据结构 。 基本思想是以递归较小的块布置树,以便许多不同大小的缓存将利用方便地适合它们的块。 这导致从RAM中的L1高速缓存到从磁盘读取的大块数据的所有内容中有效地使用高速缓存,而无需知道任何这些高速缓存层的大小的细节。


#24楼

跳过列表非常简洁。

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

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

如果你想深入介绍跳过列表,可以看一下麻省理工学院“算法导论”讲座的链接 。

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


#25楼

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


#26楼

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


#27楼

任何具有3D渲染经验的人都应该熟悉BSP树 。 通常,这是通过将3D场景结构化为可管理以便知道相机坐标和方位的方法。

二进制空间分区(BSP)是一种通过超平面将空间递归细分为凸集的方法。 该细分通过称为BSP树的树数据结构产生场景的表示。

换句话说,它是一种将复杂形状的多边形分解为凸集的方法,或者是完全由非反射角(小于180°的角度)组成的较小多边形。 有关空间分区的更一般说明,请参阅空间分区。

最初,这种方法是在3D计算机图形中提出的,以提高渲染效率。 一些其他应用包括在CAD中执行具有形状(构造实体几何)的几何操作,在机器人和3D计算机游戏中执行碰撞检测,以及涉及处理复杂空间场景的其他计算机应用。


#28楼

霍夫曼树 - 用于压缩。


#29楼

循环或环形缓冲区 - 用于流式传输等。


#30楼

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

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

  1. 数据结构与算法:22 精选练习50

    精选练习50 马上就要期末考试或者考研了.为了大家复习的方便,我精选了有关数据结构与算法的50道选择题,大家可以抽空练习一下.公众号后台回复"答案"可以获取该50道题目的答案. 0 ...

  2. arraylist 初始化_第一章 C#数据结构--数组和ArrayList

    数组是最通用的数据结构,它出现在几乎所有的编程语言里.在 C#语言中使用数组包括创建 System.Array 类型的数组对象,以及创建针对所有数组的抽象的基类型.Array 类提供了一套方法,这些方 ...

  3. JavaScript数据结构和算法

    前言 在过去的几年中,得益于Node.js的兴起,JavaScript越来越广泛地用于服务器端编程.鉴于JavaScript语言已经走出了浏览器,程序员发现他们需要更多传统语言(比如C++和Java) ...

  4. JavaScript数据结构和算法 1

    前言 在过去的几年中,得益于Node.js的兴起,JavaScript越来越广泛地用于服务器端编程.鉴于JavaScript语言已经走出了浏览器,程序员发现他们需要更多传统语言(比如C++和Java) ...

  5. 与机器学习算法有关的数据结构

    摘要: 在机器学习中需要运用到许多数据结构,掌握它们是非常重要的.希望本文能有所帮助 拥有机器学习技能是不够的.你还需要良好的数据结构的工作知识.学习更多,并解决一些问题. 因此,你已经决定不再使用固 ...

  6. java set的数据结构_set(集合)数据结构

    set(集合)是一个非常有用的数据结构.它与列表(list)的行为类似,区别在于set不能包含重复的值. 这在很多情况下非常有用.例如你可能想检查列表中是否包含重复的元素,你有两个选择,第一个需要使用 ...

  7. 《R语言机器学习:实用案例分析》——1.2节R的数据结构

    本节书摘来自华章社区<R语言机器学习:实用案例分析>一书中的第1章,第1.2节R的数据结构,作者[印度] 拉格哈夫·巴利(Raghav Bali)迪潘简·撒卡尔(Dipanjan Sark ...

  8. e - 数据结构实验之查找五:平方之哈希表_leetcode算法之哈希表

    今天该来盘一盘 哈希表 这类题目 分类别解析leetcode上的一些相关的例题路,代码采用C++与python实现. 哈希表 哈希表是一种很有用的数据结构, 其作用主要是以空间换时间, 在c++中主要 ...

  9. 一文带你认识30个重要的数据结构和算法

    摘要:掌握DSA意味着你能够使用你的计算和算法思维来解决前所未见的问题.通过了解它们,您可以提高代码的可维护性.可扩展性和效率. 本文分享自华为云社区<30 个重要数据结构和算法完整介绍> ...

最新文章

  1. php显示网卡信息,linux如何查看网卡信息
  2. python保留字分支结构_Python基础语法----缩进、注释、命名与保留字、数据类型、分支语句、函数...
  3. vscode使用汇总——常用插件、常用配置、常用快捷键
  4. Deep Learning的基础概念
  5. Python强大的格式化format
  6. python-基础知识
  7. OpenGL之利用模型视图矩阵和投影矩阵让球体自动旋转
  8. jmeter添加html,Jmeter 报告可视化 —— 配置生成测试报告仪表板,Jmeter + Jenkins 自动化构建生成 HTML 报告...
  9. 安装windows服务提示输入用户名和密码
  10. Jupyter更改主题和字体及远程访问
  11. android mysql sqlite_android内嵌的SQLite创建数据库,在哪里查看?
  12. VS解决方案目录和工程目录
  13. 家庭收支记账软件项目【Golang-面向过程】
  14. 【githubshare】开源的小说下载与阅读工具:Uncle 小说。目录解析与书源结合,支持有声小说与文本小说,可下载 mobi、epub、txt 格式文本小说
  15. (2021)建筑能耗模拟的灰箱建模与应用——综述
  16. 四十五、Kafka生产者(Producer)API介绍
  17. jQuery表单正则校验(邮箱、手机号、身份证)
  18. KubernetesAPI审计日志方案
  19. Python 简易版贪食蛇(源代码)
  20. yolov3算法模型P-R曲线绘制教程(python2,python3)

热门文章

  1. Android stdio build.gradle buildscript 里面的repositories 和allprojects里面 repositories 的区别
  2. 反射得到父类的私有字段
  3. 从前到后的CAN总线(二)
  4. Java中date和calendar的用法
  5. PHP学习笔记-文件操作1
  6. Java并发之synchronized关键字
  7. Gradle For Android
  8. iOS架构-制作静态库.a和.framework 的相互依赖(10)
  9. swift_036(Swift之第三方库SwiftyJSON篇)
  10. mysql union查询_一本彻底搞懂MySQL索引优化EXPLAIN百科全书