[英]Performance gap between sorting a list and a vector of structs. C++
我寫了一個簡單的C ++代碼來檢查數據排序的速度,以列表的形式表示,然后是矢量。
在列表的情況下,我得到時間為27秒。 對於矢量,我得到10秒。 為什么巨大的性能差距? 用於排序列表和向量的算法不一樣嗎? 即 歸並排序?
編輯:我可能在最后一點錯了。 據我所知,教科書在理論上描述排序算法時,似乎是在std::vector
意義上使用單詞list
。 我不知道向量的排序算法如何與列表的排序算法不同,所以如果有人能夠澄清那將是非常有用的。 謝謝。
//In this code we compare the sorting times for lists and vectors.
//Both contain a sequence of structs
#include <iostream>
#include <vector>
#include <list>
#include <algorithm>
#include <time.h>
#include <math.h>
#include <stdlib.h>
#include <iomanip>
using namespace std;
struct particle
{
double x;
double y;
double z;
double w;
bool operator<(const particle& a) const
{
return x < a.x;
}
};
int main(int argc, char *argv[])
{
int N=20000000;
clock_t start,stop;
vector<particle> myvec(N);
vector<particle>::iterator cii;
//Set vector values
for (cii = myvec.begin(); cii != myvec.end(); ++cii)
{
cii->x =1.0*rand()/RAND_MAX;
cii->y =1.0*rand()/RAND_MAX;
cii->z =1.0*rand()/RAND_MAX;
cii->w =1.0*rand()/RAND_MAX;
}
list<particle> mylist(N);
list<particle>::iterator dii;
//Set list values
for (cii=myvec.begin(),dii = mylist.begin(); dii != mylist.end() && cii!=myvec.end(); ++dii, ++cii)
{
dii->x =cii->x;
dii->y =cii->y;
dii->z =cii->z;
dii->w =cii->w;
}
//Sort the vector
start=clock();
sort(myvec.begin(),myvec.end());
stop=clock();
cout<<"Time for sorting vector "<<(stop-start)/(double) CLOCKS_PER_SEC<<endl;
//Sort the list
start=clock();
mylist.sort();
stop=clock();
cout<<"Time for sorting list "<<(stop-start)/(double) CLOCKS_PER_SEC<<endl;
return 0;
}
沒有使用合並排序對std::vector
進行排序(在大多數實現中,標准沒有指定算法)。
std::list
沒有O(1)隨機訪問,所以它不能使用快速排序*等算法,這需要O(1)隨機訪問速度快(這也是為什么std::sort
不能在std::list
。)
有了這個,你將不得不使用前向迭代足夠的算法,例如合並排序**。
另請參見: list.sort和std :: sort之間有什么區別?
*:libstdc ++實際上使用了introsort。
**:libstdc ++實際上使用了合並排序的變體
向量包含內存比列表更接近的內容。 這導致在排序期間更加緩存友好的訪問模式。
我真的不是C ++程序員,但我的理解是std::vector
與std::list
具有不同的性能特征。 具體來說(正如@Martinho評論的那樣):
std::vector
有O(1)隨機訪問,而std::list
則沒有。
來自cplusplus.com (我確信那里有不那么粗略的引用,請隨意加入):
矢量擅長:
- 按位置索引(恆定時間)訪問各個元素。
- 以任何順序迭代元素(線性時間)。
- 從末尾添加和刪除元素(常量攤銷時間)。
並且 :
...列出容器的優點:
- 在容器中的任何位置高效插入和移除元素(恆定時間)。
- 高效的移動元件和容器內的元件塊,甚至是不同容器之間的元件(恆定時間)。
- 以正向或反向順序(線性時間)迭代元素。
向量上的list::sort
和std::sort
不使用相同的算法。
std::sort
使用需要隨機訪問迭代器的排序算法,例如std::vector
所需的迭代器,而不是std::list
。
list::sort
專門用於列表; 它通常實現合並排序,不需要隨機訪問。
兩種算法的比較總數是O(n log n)(我說不知道我的編譯器的std::sort
實現使用的確切算法)。 交換的總數也是O(n log n),但是對於std::sort
,這意味着O(n log n)調用復制構造函數/賦值運算符,而對於list::sort
,它是指針操作。 你的結構太小,無法獲得這種優勢。 我假設只要你把一些非平凡的復制構造函數放入struct(也許std::string
就足夠了), std::list
就會獲勝。
編輯:一個std :: string成員初始化與隨機雙轉換為文本似乎是關於我的機器上的收支平衡點(x86_64-linux,gcc 4.6.2)
向量將允許恆定時間元素交換以及恆定時間隨機訪問。 列表采用線性時間進行隨機訪問,同時(可能)觸發指針更新的交換更多開銷。 我的猜測就是做了一堆交換。 而且,向量在移動存儲器中的大部分自身時更有效。
如果由於指針開銷稍微減少而交換slist <>會比列表更快,我會很好奇。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.