C++ std::map的插入提示是否有任何位置限制?

C++ std::map的插入提示是否有任何位置限制?,c++,stl,C++,Stl,我刚刚发现std::map.insert可以接受迭代器作为其第一个参数作为插入过程的搜索提示,例如map.insert(hintIterator,insertElement)。但是对于提示元素有任何职位要求吗?它需要在插入位置之前还是之后?顺便问一下,提示迭代器的位置对插入效率有多大影响 来自概念: 带提示的Insert通常是对数的,但如果t在p之前插入,则它是固定摊销时间。 关于迭代器的提示仅此而已: 参数p是一个提示:它指向搜索将开始的位置。 它可以是从begin()到end()的任意位置。

我刚刚发现std::map.insert可以接受迭代器作为其第一个参数作为插入过程的搜索提示,例如
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:看起来没有区别-请参阅更新的答案中的数字。