[英]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,2和3這是最快的?
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_set
第4版。 事實證明,最好的表現是后者, 4用unordered_set
代替set
。
順便說一句,如果考慮到set
和sort
都有點過分,那么經驗發現並不太令人驚訝:它們保證了不相等元素的相對順序。 例如,輸入4,3,5,2,4,3
將導致唯一值2,3,4,5
排序輸出。 如果您可以按任意順序使用唯一值,即3,4,2,5
,則這是不必要的。 當您使用unordered_set
它不保證順序,只保證唯一性,因此它不必執行確保不同元素順序的額外工作。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.