【问题标题】:Queue-like data structure with random access element removal具有随机访问元素移除的类似队列的数据结构
【发布时间】:2012-02-28 21:55:55
【问题描述】:

是否有类似队列的数据结构也支持在任意点移除元素?入队和出队最常发生,但在速度方面,中间队列元素删除必须相似,因为可能存在最常见的操作。性能的一致性比绝对速度更重要。时间比记忆更重要。队列长度很小,在绝对峰值负载下不到 1,000 个元素。如果不是很明显,我会明确说明:不需要随机插入。

已标记 C++,因为那是我的实现语言,但我没有使用(也不想使用)任何 STL 或 Boost。仅限纯 C 或 C++(我会将 C 解决方案转换为 C++ 类。)

编辑:我想我想要的是一种也有队列接口的字典(或也有字典接口的队列),这样我就可以做这样的事情:

Container.enqueue(myObjPtr1);
MyObj *myObjPtr2 = Container.dequeue();
Container.remove(myObjPtr3);

【问题讨论】:

  • 为什么不用 STL 或 Boost ?它们是纯 C++。否则,您需要编写自己的数据结构。
  • 没有 STL?那你就得自己写了。我会用一棵树来更新左子节点中有多少个节点。应该是 log(n) 一切。
  • (I will wrap C solutions in a C++ class.)我拒绝继续阅读
  • @TimKemp:编程就是解决问题。库是您的问题中已经解决的部分。尽可能不使用它们既浪费又荒谬。
  • @Lightness:是的,我们以前去过那里,我坚定地支持 STL-is-not-the-std-lib 阵营。然而,大部分 STL 已被合并到 C++ 标准库中,我认为它是 C++ 的一部分(毕竟它是标准论文的主要部分)。

标签: c++ data-structures


【解决方案1】:

我认为双链表正是你想要的(假设你不想要优先级队列):

  1. 在两端轻松快速地添加元素
  2. 从任何地方轻松快速地删除元素

您可以使用std::list 容器,但是(在您的情况下)很难删除元素 如果您只有一个指向元素的指针(或引用)(包装在 STL 的列表元素中),则从列表的中间开始,但是 你没有迭代器。如果使用迭代器(例如存储它们)不是一种选择 - 那么实现双链表(即使使用元素计数器)应该很容易。如果您实现自己的列表 - 您可以直接操作指向元素的指针(每个元素都包含指向其两个邻居的指针)。如果您不想使用 Boost 或 STL,这可能是最好的选择(也是最简单的),并且您可以控制一切(您甚至可以为列表元素编写自己的块分配器以加快事物)。

【讨论】:

  • 请注意,链表不允许快速删除“所有位置的元素”,因为finding列表中的元素是O(n)。如果您被要求删除值为k [或索引i] 的元素,它将是O(n)
  • 那你没有理解我的评论。如果我有一个指向 list 元素 的指针(其中包含指向其两个邻居的指针),那么我还需要找到什么?
  • 好的,这听起来很有趣,谢谢,该方法应该有效。我会调查的。
【解决方案2】:

一种选择是使用顺序统计树,这是一种增强的树结构,支持对每个元素的 O(log n) 随机访问,以及在任意点的 O(log n) 插入和删除.在内部,顺序统计树被实现为带有额外信息的平衡二叉搜索树。因此,查找比在标准动态数组中要慢,但插入要快得多。

希望这会有所帮助!

【讨论】:

  • 对末端的插入/移除比deque 慢,但对中间更快。
  • 谢谢,有参考实现或论文吗?除了一些其他问题之外,在这些方面的搜索并没有太多结果。
  • @Tim Kemp- 我在 C:geeksforgeeks.org/archives/10379 中找到了这个实现。一段时间以来,我一直想在 C++ 中实现这个结构,所以我想我可能会在有空闲时间的时候这样做(不知道多久会这样)。如果我这样做,我会在这里发布。
【解决方案3】:

您可以结合使用链表和哈希表。在 java 中它被称为LinkedHashSet

思路很简单,有一个元素的链表,还要维护一个(key,nodes)hash map,其中node是指向链表中相关节点的指针,key是key代表这个节点。

请注意,基本实现是set,需要一些额外的工作才能使此数据结构允许欺骗。

这个数据结构允许O(1) 头/尾访问,以及O(1) 访问列表中的任何元素。 [平均全部是电动的]

【讨论】:

  • 作为补充说明,这可以通过 std::unordered_set 和 Boost.Intrusive 列表轻松实现。
  • 只是一个想法 - 如果队列中有重复的元素会发生什么?你会如何区分它们?另外,如果你想按索引删除,你会怎么支持呢?
  • @templatetypedef:需要做更多的工作来支持重复 - 正如我所提到的。一个可能的解决方案可能是map<key,list<node>> - 但是当您的列表有很多欺骗时,它会受到影响。 LinkedHashSet 的索引删除确实存在问题 - 我想任何有效的解决方案都需要将列表转换为跳过列表[带有索引计数],这将导致操作衰减到 O(logn)。这里有一个明显的权衡:LinkedHashSetO(1) 性能并不是免费的。
  • 如果“随机访问”是按顺序,也就是列表中元素的索引,这将不起作用
猜你喜欢
  • 2015-09-17
  • 1970-01-01
  • 1970-01-01
  • 2016-12-11
  • 1970-01-01
  • 1970-01-01
  • 2013-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多