簡體   English   中英

對std :: map的插入提示有任何位置限制嗎?

[英]Is there any position limitation on the insert hint for std::map?

我剛剛發現std :: map.insert可以接受迭代器作為其第一個參數作為插入過程的搜索提示,例如map.insert(hintIterator, insertElement); 但是提示元素是否有任何位置要求? 是否需要在插入位置之前或之后? 順便說一下,提示迭代器位置對插入效率有多大影響?

它可以是從begin()end()任何位置。 如果傳入與理想插入位置相對應的迭代器,則可以大大提高插入成本,以便搜索正確的位置。

來自SGI STL網站

復雜性保證

具有提示的插入通常是對數的,但如果在p之前插入t,則它是分攤的常量時間。

要理解這是為什么,請考慮正在應用的算法。 std::map具有以某種順序排列的項目,並且為了找到正確的插入點,必須遍歷項目,直到找到一個項目(“A”)必須在新數據和下一個項目之前的位置(“ B“)必須遵循它。 事先給定這個位置,可以消除搜索。

新數據必須介於這兩個項目之間,並更新它們之間的鏈接。 至少(對於可向前迭代的容器),必須更新項目A以指向新數據,該數據隨后指向B.如果包含的是反向可迭代的,則還必須更新B以指向新數據。

應該如何指定位置? 必須知道A或B是否枯萎。正如Cubbi所指出的那樣,並且在alt.comp.lang.learn.c-cpp上進行了討論,2003標准在提示應該是什么上有所不同。 SGI文檔建議B是需要的,而標准建議A.可能(假設std::map具有bidriectional迭代器)它並不重要。 不過,我建議較低項目(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;
}

在我運行MinGW GCC 4.5的小型上網本上,我得到了:

提示始終是前一個值的位置
94 109 109 109 109 109 110 110 110 94
提示始終是以下值的位置
109 94 109 94 110 110 109 109 110 110
提示始終是容器的開始
188 172 172 187 172 172 235 187 172 187
沒有提示
172 171 172 172 172 172 172 172 171 172

所以我要說任何一方的暗示都給出了相同的結果,並且總是好於沒有任何暗示。 選擇一個糟糕的提示位置(例如開始)比沒有提示更糟糕。

Unique Sorted Associative Container概念:

具有提示的插入通常是對數的,但如果在p之前插入t,則它是分攤的常量時間。

只有這個關於提示迭代器:

參數p是一個提示:它指向搜索開始的位置。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM