【发布时间】:2017-08-25 12:55:50
【问题描述】:
作为一个简单的开始
Map<key,val> map1=//filled up in some way;
Map<key,val> map2;
map2.insert(map1.begin(),map1.end());
我们知道map::insert 是 O(log(n)),没有提供任何提示。这是否意味着上述运行在 O(nlog(n)) 中,或者它是否使用 map1 已经排序并简单地插入到正确位置(递增当前迭代器)的事实?因为 map1 已经排序,我们应该能够在线性时间内做到这一点。怎么样
std::copy(map1.begin(),map1.end(),map2.end());
它是每次在 O(log(n)) 中插入,还是在 O(1) 中复制到通过递增迭代器标记的尊重位置?
也许是一个更具说明性的例子
template<class InIter, class OutIter, class ResIter>
ResIter foo(InIter first, OutIter last, ResIter res){
while(first!=last){
res=*first;
++first;
++res;
}
return res;
}
当我们处理映射迭代器时,这是否运行在 O(n) 或 O(nlog(n)) 中?插入是 O(log(n)),还是 O(1),因为我们指定了位置,即*res=*first?
为清楚起见进行编辑:
会
*res=*first
表现得像
map2.insert(res,*first)
意思是,插入到map2中,使用指向正确位置的迭代器res作为提示,使其成为O(1),还是执行常规的O(log(n))插入?
【问题讨论】:
-
好问题。请注意,如果您使用实际的复制构造函数,您可能会得到一个有效的副本。另一种选择是在循环中插入,使用
end()作为插入提示,如果您按顺序阅读源映射,这始终是正确的。 (您可以使用copy和插入迭代器来做到这一点。) -
std::copy(map1.begin(),map1.end(),map2.end());如果map1不为空,则具有未定义的行为,因为map2.end()不可取消引用。 -
有没有办法在通过迭代器插入时使用提示,例如 *res=*first ?我问是因为这是一个玩具示例,在真实示例中,它不是要复制整个地图。关于您的评论,我应该将其更改为 map2.begin()?
-
将有序数据插入平衡二叉树实际上是更糟糕的情况,因为每次插入后都必须重新平衡树。如果树没有重新平衡,所有节点都将沿着树的一个分支创建。
-
但是 map1 的内容已经排序,这就是为什么我声称我们应该能够在线性时间内做到这一点。也许我误解了你。
标签: c++ iterator time-complexity stdmap