C ++中的订单维护数据结构

时间:2015-09-29 08:43:40

标签: c++ algorithm data-structures

我正在寻找能够有效解决Order-maintenance problem的数据结构。换句话说,我需要有效率

  • 插入(在中间),
  • 删除(中间),
  • 比较容器中元素的位置。

我找到了讨论这个问题的好文章:

算法非常有效(某些状态对于所有操作都是O(1)),但它们似乎并不是微不足道的,我想知道是否存在这些或类似数据结构的开源C ++实现。

我见过related topic,建议使用一些时间复杂度为O(log n)的简单方法,但是我在这里寻找现有的实现。

如果在其他一些流行语言中有一个例子,它也会很好,这样我至少可以在尝试自己实现它之前先尝试一下。

详情

我要去

  • 维护一个指向对象的指针列表,
  • 我不时需要更改对象的顺序(删除+插入),
  • 给定一个对象子集,我需要能够快速对它们进行排序并按正确顺序处理它们。

注意

标准订购容器(std :: set,std :: map)不是我想要的,因为它们会维护我的订单,但我需要自己订购元素。类似于我对std :: list的处理,但是位置比较是线性的,这是不可接受的。

3 个答案:

答案 0 :(得分:4)

如果您正在寻找易于实施且高效的解决方案,您可以使用平衡二叉搜索树(AVL或红黑树)构建此结构。您可以按如下方式实施操作:

  • 插入(X,Y)(在总排序中 Y 之后立即插入 X ) - 如果 X 没有一个正确的孩子将 X 的正确孩子设为 Y ,否则让 Z 成为树的最左边的节点使用root X.right (这意味着最低的 Z = X.right.left.left.left ... ,这不是NULL)并设置它' s Z 的左孩子 Y 。必要时保持平衡。您可以看到总复杂度为O(log n)。
  • 删除(X) - 只需删除节点X,因为您通常会从树中删除。复杂性O(log n)。
  • 比较(X,Y) - 找到从 X 到根的路径以及从 Y 到根的路径。您可以从这两个路径中找到 Z X Y 的最低共同祖先。现在,您可以比较 X Y ,具体取决于它们是在 Z 的左侧还是右侧子树中(它们可以'同时在同一个子树中, Z 不会成为他们最低的共同祖先。复杂性O(log n)。

因此,您可以看到此实现的优势在于所有操作都具有复杂度O(log n),并且易于实现。

答案 1 :(得分:0)

您可以使用类似于使用std :: list

的跳过列表

跳过清单最初是由William Pugh在1989年描述的。 引用作者:

跳过列表是一种概率数据结构,似乎可能取代平衡树作为许多应用程序的首选实现方法。跳过列表算法与平衡树具有相同的渐近预期时间范围,更简单,更快速,占用空间更少。

http://drum.lib.umd.edu/handle/1903/542

答案 2 :(得分:-2)

STL是解决您问题的方法 它是标准的,经过验证的高效容器以及支持它们的算法。 STL中的几乎所有容器都支持您提到的操作。

似乎std::deque对你所指的任务具有最佳品质:
1)插入:从O(1)复杂度到后面和前面都是 2)删除:与连续容器不同,std::deque::erase是O(N),其中N是删除的项目数。这意味着只删除一个项目具有O(1)
的复杂性 3)位置比较:使用std::advancestd::deque的复杂度为O(N)
4)排序:使用std::sort,通常会对任务使用快速排序,并将在O(n * log n)中运行。至少在MSVC ++中,该函数试图猜测给定容器的最佳排序算法是什么。

在尝试彻底使用STL之前,不要尝试使用开源解决方案/构建自己的库!