簡體   English   中英

從vector <>中刪除重復項的最快方法

[英]Fastest way to remove duplicates from a vector<>

正如標題所說,我在腦海中有一些方法可以做到,但我不知道哪個是最快的。

所以我們假設我們有一個帶有一些值的vector<int> vals

1

我的vals添加后

sort(vals.begin(), vals.end());
auto last = unique(vals.begin(), vals.end());
vals.erase(last, vals.end());

2

添加我的vals后轉換為set:

set<int> s( vals.begin(), vals.end() );
vals.assign( s.begin(), s.end() );

3

當我添加我的vals ,我檢查它是否已經在我的向量中:

if( find(vals.begin(), vals.end(), myVal)!=vals.end() )
    // add my val

4

從頭開始使用一套

好的,我有這四種方法,我的問題是:

1從1,23這是最快的?
2比前3 快4嗎?
3在將矢量轉換為設置后,在2處使用該集合做我需要做的事情或者我應該執行vals.assign( .. )並繼續我的向量更加方便嗎?

問題1 :1和2都是O(n log n),3是O(n ^ 2)。 在1到2之間,它取決於數據。

問題2 :4也是O(n log n),如果你有很多重復項,它可以優於1和2,因為它只存儲每個副本的一個副本。 想象一下,百萬個價值都是平等的。

問題3 :嗯,這實際上取決於你需要做什么。

唯一可以說不知道更多的是你的替代數字3漸漸比其他數字更差。

如果您使用的是C ++ 11並且不需要排序,則可以使用std::unordered_set ,它是一個哈希表,並且可以比std::set快得多。

選項1將擊敗所有其他選項。 復雜度只是O(N log N),向量的連續記憶保持低常數因子。

std :: set通常會受到非連續分配的影響。 訪問它們不僅速度慢,只需創建它們也需要很長時間。

這些方法都有其缺點,盡管(1)值得關注。

但是,看看第5個選項:請記住,您可以使用data()函數訪問向量的數據緩沖區。 然后,請記住,由於向量只會變小,所以不會進行重新分配,應用您在學校學到的算法:

unduplicate(vals.data(), vals.size());

void unduplicate(int* arr, std::size_t length) /*Reference: Gang of Four, I think*/
{
    int *it, *end = arr + length - 1;
    for (it = arr + 1; arr < end; arr++, it = arr + 1){
        while (it <= end){
            if (*it == *arr){
                *it = *end--;
            } else {
                ++it;
            }
        }
    }
}

如果這是必需的,最后調整矢量大小。 這絕不會比O(N ^ 2)差,所以優於插入排序或排序然后刪除方法。

如果您可以采用它,那么您的第4個選項可能是個主意。 描述性能。 否則使用我的算法從20世紀60年代。

我有一個類似的問題,最近,與1,2,4個試驗,以及與unordered_set4版。 事實證明,最好的表現是后者, 4unordered_set代替set

順便說一句,如果考慮到setsort都有點過分,那么經驗發現並不太令人驚訝:它們保證了不相等元素的相對順序。 例如,輸入4,3,5,2,4,3將導致唯一值2,3,4,5 排序輸出。 如果您可以按任意順序使用唯一值,即3,4,2,5 ,則這是不必要的。 當您使用unordered_set它不保證順序,只保證唯一性,因此它不必執行確保不同元素順序的額外工作。

暫無
暫無

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

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