【问题标题】:Removing specific node(s) from STL List从 STL 列表中删除特定节点
【发布时间】:2012-05-04 05:03:27
【问题描述】:

我需要维护一个项目列表(一些对象),并支持以下操作:

  • 在末尾插入
  • 从任何位置删除

STL 列表似乎是正确的选择。但是,我怎样才能在恒定时间内进行第二次操作?我可以将指向每个节点的指针保存在某处并直接删除它们,但是擦除需要一个迭代器,所以这不起作用。

示例用法:

items = list<myobj>..
items.push_back(obj1)
items.push_back(obj2)
items.push_back(obj3)
items.remove(obj2) // <- How to do this in constant time.

如果 push_back 以某种方式允许访问节点,我可以使用:

map[obj1] = items.push_back(obj1)
items.remove(map[obj1])

一种选择是在地图中使用迭代器,有没有更简单的方法?

【问题讨论】:

  • 不保存指针,就不能只保存迭代器吗?另外,恒定时间是什么意思?简单地从 std::list 中的任何位置删除一个对象是恒定的,但找到一个对象不是。
  • 问题是如果列表中有 n 个项目,我必须保存 n 个迭代器。这看起来不像是一个优雅的解决方案(顺便说一句,我是 C++ 新手)
  • 根据您的用例,您可能只想使用 std::vector。删除项目的效率相对较低,O(n),但访问它们的时间是恒定的,如果您可以将项目设置为空(如果您正在存储指针)或对象中的特殊值。当然会占用更多内存,但这是个问题吗?
  • 您需要一个项目列表还是一个集合?这个收藏的目的是什么?您将对其执行哪些操作?搜索?迭代?你将如何消费它们?
  • 操作是上面提到的唯一操作。我将编辑问题并添加一个示例。

标签: c++ stl linked-list


【解决方案1】:

折衷方案是像大多数 std::set 实现一样使用红黑树。插入、搜索和删除的时间为 O(log n)。树基本上是最终的折衷数据结构。他们没有什么了不起的,但他们总是把工作做得足够好。

否则,请同时使用链表和向量来分析您的代码,并确定调整向量大小是否真的很糟糕(这取决于您执行此操作的频率)。


可能有更好(不优雅但非常有效)的解决方案可以解决您的问题。您还没有提到您将如何使用该列表,但如果您可以将一个值留作未使用,您可以使用一个向量并将一个元素简单地标记为已删除,而不是实际删除它。或者使用一个向量和一个单独的位集(或 C++03 vector&lt;bool&gt;)告诉你一个项目是否被删除或有效。要删除它,您只需翻转位图中的位。迭代时,只记得在处理内容之前检查删除位图。如果内存不是问题,只关心速度和易用性/清晰度,请将vector&lt;object&gt; 替换为vector&lt;pair&lt;bool, object&gt;&gt;,其中bool 是删除标志。

【讨论】:

  • +1 用于 RB-trees,我们还可以在其中存储指向非唯一对象的指针。
【解决方案2】:

您可能想查看Boost.MultiIndex。这允许您在数据结构上组合多个索引。因此,您可以以线性空间开销为代价对任何元素进行恒定时间查找和删除。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-23
    • 1970-01-01
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多