C++ std::map的插入提示是否有任何位置限制?
我刚刚发现std::map.insert可以接受迭代器作为其第一个参数作为插入过程的搜索提示,例如C++ std::map的插入提示是否有任何位置限制?,c++,stl,C++,Stl,我刚刚发现std::map.insert可以接受迭代器作为其第一个参数作为插入过程的搜索提示,例如map.insert(hintIterator,insertElement)。但是对于提示元素有任何职位要求吗?它需要在插入位置之前还是之后?顺便问一下,提示迭代器的位置对插入效率有多大影响 来自概念: 带提示的Insert通常是对数的,但如果t在p之前插入,则它是固定摊销时间。 关于迭代器的提示仅此而已: 参数p是一个提示:它指向搜索将开始的位置。 它可以是从begin()到end()的任意位置。
map.insert(hintIterator,insertElement)代码>。但是对于提示元素有任何职位要求吗?它需要在插入位置之前还是之后?顺便问一下,提示迭代器的位置对插入效率有多大影响 来自概念:
带提示的Insert通常是对数的,但如果t在p之前插入,则它是固定摊销时间。
关于迭代器的提示仅此而已:
参数p
是一个提示:它指向搜索将开始的位置。
它可以是从begin()
到end()
的任意位置。如果传入与理想插入位置对应的迭代器,则可以大大提高搜索正确位置的插入成本
从网站
复杂性保证
带提示的Insert在中是对数的
一般,但它是摊销常数
如果立即插入t,则为时间
在p之前
要理解这一点,请考虑正在应用的算法<代码>标准::地图
以某种顺序排列项目,为了找到正确的插入点,必须遍历项目,直到找到一个位置,其中一个项目(“a”)必须位于新数据之前,下一个项目(“B”)必须位于新数据之后。提前给定此位置,可以消除搜索
新数据必须介于这两个项目之间,并更新它们之间的链接。至少(对于正向可移植容器)项目A必须更新为指向新数据,随后指向B。如果包含的是反向可移植的,则B也必须更新为指向新数据
应如何指定位置?人们必须知道威瑟尔A或B。正如库比指出的,在2003年的标准中讨论的关于暗示应该是什么的不同。SGI文档建议使用B,而标准建议使用A。可能(考虑到std::map
具有双向迭代器),这并不重要。不过,我建议,下一项(A)的位置最好,因为您可以始终期望能够继续向前搜索
更新:因为经过教育的猜测在验证之前是无用的,所以这里有一个快速测试:
#include <ctime>
#include <map>
#include <iostream>
int main() {
typedef std::map<unsigned int,unsigned int> map;
const unsigned int k=100000;
const unsigned int reps=10;
// Avoid edge cases by padding either end
map srcMap;
{
for(unsigned int i=0; i!=k;++i) {
srcMap.insert(std::make_pair(i,i));
}
unsigned int l=3*k;
for(unsigned int i=2*k; i!=l;++i) {
srcMap.insert(std::make_pair(i,i));
}
}
std::cout << "Hint is always the position of the preceding value\n";
for(unsigned int i=0; i!=reps;++i)
{
map testMap(srcMap);
map::iterator p=testMap.lower_bound(k-1);
unsigned int l=2*k;
std::clock_t start = std::clock();
for(unsigned int i=k; i!=l;++i) {
p=testMap.insert(p,std::make_pair(i,i));
}
std::clock_t end = std::clock();
std::cout << static_cast<double>((end - start) ) << " ";
}
std::cout << std::endl;
std::cout << "Hint is always the position of the following value\n";
for(unsigned int i=0; i!=reps;++i)
{
map testMap(srcMap);
map::iterator p=testMap.lower_bound(2*k);
unsigned int l=k-1;
std::clock_t start = std::clock();
for(unsigned int i=2*k-1; i!=l;--i) {
p=testMap.insert(p,std::make_pair(i,i));
}
std::clock_t end = std::clock();
std::cout << static_cast<double>((end - start) ) << " ";
}
std::cout << std::endl;
std::cout << "Hint is always the start of the container\n";
for(unsigned int i=0; i!=reps;++i)
{
map testMap(srcMap);
unsigned int l=2*k;
std::clock_t start = std::clock();
for(unsigned int i=k; i!=l;++i) {
testMap.insert(testMap.begin(),std::make_pair(i,i));
}
std::clock_t end = std::clock();
std::cout << static_cast<double>((end - start)) << " ";
}
std::cout << std::endl;
std::cout << "No hint\n";
for(unsigned int i=0; i!=reps;++i)
{
map testMap(srcMap);
unsigned int l=2*k;
std::clock_t start = std::clock();
for(unsigned int i=k; i!=l;++i) {
testMap.insert(std::make_pair(i,i));
}
std::clock_t end = std::clock();
std::cout << static_cast<double>((end - start)) << " ";
}
std::cout << std::endl;
return 0;
}
#包括
#包括
#包括
int main(){
typedef std::map;
常数无符号整数k=100000;
常量无符号整数代表=10;
//通过填充任意一端避免边缘情况
地图;
{
for(无符号整数i=0;i!=k;++i){
insert(std::make_pair(i,i));
}
无符号整数l=3*k;
for(无符号整数i=2*k;i!=l;++i){
insert(std::make_pair(i,i));
}
}
std::如果在p之后立即插入t,是否为摊销固定时间?@Thomson tan:是的,应该是相同的,并且可能在p之后插入更好。请参阅更新的答案。@Thomson tan:看起来没有区别-请参阅更新的答案中的数字。