std::map<t1, t2>::erase(iterator position) 的工作?

Posted

技术标签:

【中文标题】std::map<t1, t2>::erase(iterator position) 的工作?【英文标题】:Working of std::map<t1, t2>::erase(iterator position)? 【发布时间】:2013-03-14 06:00:04 【问题描述】:

我在cplusplus.com 上读到,通过将迭代器作为参数传递来删除std::map 中的元素的操作是常数时间。

如果我没有错(如果我错了,请纠正我)迭代器基本上是指向映射中元素的指针,++ 运算符只是返回当前元素的有序后继我猜这就是排序的方式结果是在遍历std::map 时实现的。

现在如果地图是一棵红黑树,那么删除一个元素(使用它的地址)不应该是对数时间操作吗,我想知道他们如何在恒定时间内做到这一点(除非有一个高度浪费内存的替代方案这样做)。

【问题讨论】:

相关***.com/questions/12078795/… 【参考方案1】:

首先,我会警惕您从 cplusplus.com 获得的任何信息;已知该网站存在一些错误。

访问cppreference.com,我们了解到复杂性是摊销常数时间。这意味着任何 n 个erase 操作序列都应该花费 O(n) 时间,即使单个擦除操作花费的时间大于 O(1)。

事实证明,从红/黑树中插入或删除所需的时间最终计算如下:每次插入或删除需要时间 O(log n) 才能找到节点的位置,但随后只摊销 O(1) 工作以插入或删除元素。这意味着从红/黑树中插入或删除节点所完成的工作主要是确定该节点去哪里所需的工作,而不是事后重新平衡树所需的工作。结果,如果您已经有一个指向红/黑树的指针并想要删除该元素,则只需执行摊销 O(1) 工作即可删除该元素。每个单独的删除可能需要一些时间(最多 O(log n)),但在 n 个操作的流中完成的总工作最多为 O(n)。

请注意,标准不要求std::map 使用红/黑树。它可以使用另一种类型的数据结构(例如,splay tree、scapegoat tree 或确定性skiplist),这也保证了这种时间复杂度。然而,有趣的是,并非所有平衡二叉搜索树结构都支持分期 O(1) 删除。例如,AVL tree 没有此保证。

希望这会有所帮助!

【讨论】:

其实cplusplus.comalso says是摊销常数。 @ArmenTsirunyan- 啊,谢谢!也就是说,我仍然坚持我最初的主张。 :-)【参考方案2】:

如果你传递一个迭代器到map来移除元素,它是根据http://www.cplusplus.com/reference/map/map/erase/摊销的常数时间。

摊销的常数时间是指“每次操作所花费的平均时间,如果您执行许多操作”。因此,可能有一些操作需要比常数时间更长的时间,但如果你多次执行相同的操作,它就是摊销常数。

【讨论】:

以上是关于std::map<t1, t2>::erase(iterator position) 的工作?的主要内容,如果未能解决你的问题,请参考以下文章

成员函数指针和继承

线程之间的同步

c++ map clear相关内存会清空吗?

c++ map clear相关内存会清空吗

如果 T2 是 T1 属性之一,如何检查 <T1> 的集合是不是包含 <T2> 的集合?

C# 将 Func<T1, object> 转换为 Func<T1, T2>