实践中的高级数据结构

时间:2008-12-23 15:49:36

标签: data-structures

在我编程的10年里,我可以计算出我一方面使用过的数据结构的数量:数组,链表(我将堆栈和队列放在一起)和字典。考虑到我写的几乎所有应用程序都属于数据形式/ CRUD类别,这并不奇怪。

我从来不需要使用红黑树,跳过列表,双端队列,循环链表,优先级队列,堆,图或任何已经研究过的数十种奇异数据结构。过去50年。我觉得我错过了。

这是一个开放式问题,但这些“异国情调”的数据结构在实践中使用在哪里?有没有人有使用这些数据结构解决特定问题的实际经验?

15 个答案:

答案 0 :(得分:29)

一些例子。他们很模糊,因为他们为雇主工作:

  • 获得前N个结果的heap会产生Google风格的搜索结果。 (从索引中的候选者开始,线性地遍历它们,将它们筛选到最大大小为N的最小堆中。)这是用于图像搜索原型。

  • Bloom filters减少了某些数据的大小,这些数据是关于数百万用户已经看到的适合现有服务器的数量(为了速度,所有数据都必须在RAM中);原始设计只需要为该数据库提供许多新服务器。

  • 对于推荐引擎,triangular array representation将密集对称数组的大小减半(出于同样的原因再次使用RAM)。

  • 用户必须根据某些关联进行分组; union-find使这一切变得简单,快速,准确,而不是缓慢,愚蠢和近似。

  • 根据周边人群的驾驶时间选择零售网站的应用程序使用Dijkstra shortest-path优先级队列。其他GIS工作利用了quadtreesMorton索引。

了解数据结构中的内容 - 土地派上用场 - “实验室中的数周可以节省您在图书馆的工作时间”。由于规模的原因,使用bloom-filter案例是值得的:如果问题出现在启动而不是Yahoo,我会使用一个普通的旧哈希表。我认为其他任何例子在任何地方都是合理的(尽管现在你不太可能自己编码)。

答案 1 :(得分:12)

B-trees在数据库中。

R-trees用于地理搜索(例如,如果我有10000个形状,每个形状都有一个分散在二维平面周围的边界框,这些形状中的哪一个与任意边界框B相交?)

deques中表单的

C++ STL是可增长的向量(比链接列表更有内存效率,并且在中间“查看”任意元素的常量时间)。据我所知,我从来没有完全使用deque(从两端插入/删除),但它足够通用,可以将它用作堆栈(从一端插入/删除)或队列(插入)一端,从另一端删除)并且还具有高性能访问权限,可以查看中间的任意元素。

我刚刚读完Java Generics and Collections - “仿制品”部分让我头疼,但收藏品部分很有用&他们指出跳过列表和树之间的一些区别(两者都可以实现地图/集):跳过列表为您提供从一个元素到下一个元素的内置恒定时间迭代(树是O(log n))并且更简单在多线程情况下实现无锁算法。

优先级队列用于安排其他事项(这里是简要讨论应用程序的webpage);堆通常用于实现它们。我还发现heapsort(至少对我来说)是最容易理解和实现的O(n log n)种类。

答案 2 :(得分:8)

它们经常在图书馆的幕后使用。例如,有序字典数据结构(即按键排序遍历的associative array)很可能不使用red-black tree.实现

许多数据结构(splay trees浮现在脑海中)对于它们在某些情况下的最佳行为很有意义(在splay树的情况下为temporal locality of reference),因此它们主要与这些情况相关。在大多数情况下,对这些数据结构的工作知识的真正好处是能够在适当的情况下使用它们并合理地理解它们的行为。

进行排序,例如:

  • 在大多数情况下quicksort 或者改进的快速入口 当另一种方法时 各个细分市场足够小 通常是最快的排序 大多数用途的算法。 但是,quicksort倾向于显示 次优行为 几乎排序的数据。

  • heap sort的主要优点是可以完成。{ 原位最小的中间体 存储,这非常好 用于内存受限 系统。虽然它比较慢 平均而言(虽然仍然是n log(n)), 它不会受苦 从糟糕的最坏情况表现 快速排序。

  • 第三个例子是merge sort,可以完成 顺序,使它成为最好的 对数据集进行排序的选择很多 大于你的主存。 另一个名字是 '外部排序',意思是你可以 使用外部存储(磁盘或 胶带)用于中间结果。

答案 3 :(得分:4)

这取决于您工作的抽象级别。

我知道我和你有过相似的经历。在目前大多数软件开发的抽象层面。字典和列表是我们使用的主要数据结构。

我认为如果你低头看下级代码,你会看到更多的“奇特”数据结构。

答案 4 :(得分:3)

答案 5 :(得分:2)

我认为您看到花哨的数据结构使用了大多数更高级别的算法。我想到的主要例子是A *,它使用由堆实现的图形和优先级队列。

答案 6 :(得分:2)

在财务方面,您需要使用树来计算依赖于许多其他动态值的工具的价值。电子表格具有类似的依赖树,编译器在转换为机器代码之前会创建一个抽象语法树。

答案 7 :(得分:2)

Fibonacci heaps用于Dijkstra's algorithm的有效实施。

答案 8 :(得分:1)

是的,有时候。我看到的问题是,虽然很多人都认识他们,但他们不知道如何真正应用它们。大多数人都会回归到数据链表等。在大多数情况下,他们会把工作完成为一种更高级的数据结构(有时你真的必须“踢它”到位),它们效率会降低。人们倾向于为他们做更容易的事情,但这不一定是做某事的最佳方式。我不能错过它们,我相信我也是这样做的,但这就是为什么你在编程中没有看到很多“高级”的概念。

答案 9 :(得分:1)

我刚刚通过在stackoverflow上询问question来找到图形用途:)

答案 10 :(得分:0)

我使用循环链表来实现我将要永远迭代的队列(在C中),即网络连接队列。

但是我发现当我使用更高级别的语言时,我并不觉得自己很难以这种方式实现队列,因为我可以动态地增长和缩小列表而不必过多担心它。当然,这是一个性能价格,因为我对内存分配的时间控制较少,但这是我们为能够拥有非常灵活的列表所付出的代价之一。

答案 11 :(得分:0)

当代码需求决定时,您会看到更复杂的数据结构。通常我会在较低级别处理更复杂的代码时看到这一点,即在核心操作系统中,编写类库的基本部分(实现字符串,数组等),编写外部性能或多线程代码我认为它们发挥重要作用的另一个地方是实现特定的算法,搜索,采样,统计分析,优化等算法通常都是用特定的数据结构编写的。

答案 12 :(得分:0)

我经常使用集合,排序集合(始终按排序顺序保留其元素,并支持快速元素插入)和惰性列表。

答案 13 :(得分:0)

平衡树(红黑等)通常用于抽象数据类型的实现。

只有相对较少的抽象数据类型,例如

  • 列表
  • 地图
  • 有序地图
  • 多地图
  • 订购多地图
  • 优先级队列(看起来很像有序的多地图)

同样,一组看起来很像地图,但你不需要值,只需要键。

我发现其中大部分都是不时有用的;优先级队列是一种非常有用的数据结构,并且具有各种算法的应用程序(例如,调度,路径查找等)。

你说“字典”,你可能意味着地图或有序地图。

某些地图是无序的(通常实现为哈希) - 这是有序地图的有用子集。

答案 14 :(得分:0)

我使用循环列表进行缓存。

C ++类模板提供了获取对象的接口(Cache<Obj, Len>)。它的几个instatinations返回不同类型的“屏幕”,如图形界面的不同视图。在幕后,如果请求的“屏幕”不可用,则会创建(昂贵的操作)并将其推到环形缓冲区的头部,推出最旧的屏幕(卸载其纹理等)。

因此,总是从硬盘读取一堆图像文件,只是将所有图像加载到RAM并永久保存它们之间实现折衷。折衷方案由各种缓冲区的长度控制。