排序列表和结构向量之间的性能差距。C++; 我编写了一个简单的C++代码,检查排序数据的速度,以列表的形式表示,然后用向量表示。p>
对于列表,我得到的时间是27秒。对于一个向量,我得到10秒。为什么会出现巨大的性能差距?用于排序列表和向量的算法不一样吗?即。合并排序 编辑:最后一点我可能错了。据我所知,教科书在理论上描述排序算法时,似乎是在排序列表和结构向量之间的性能差距。C++; 我编写了一个简单的C++代码,检查排序数据的速度,以列表的形式表示,然后用向量表示。p>,c++,stl,vector,C++,Stl,Vector,对于列表,我得到的时间是27秒。对于一个向量,我得到10秒。为什么会出现巨大的性能差距?用于排序列表和向量的算法不一样吗?即。合并排序 编辑:最后一点我可能错了。据我所知,教科书在理论上描述排序算法时,似乎是在std::vector的意义上使用单词list。我不知道怎么做 向量的排序算法与列表的排序算法有何不同,所以如果有人能澄清这一点,那将非常有帮助。多谢各位 //In this code we compare the sorting times for lists and vectors.
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;
结构粒子
{
双x;
双y;
双z;
双w;
布尔运算符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;
}
列表列表(N);
列表::迭代器dii;
//设置列表值
对于(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;
}
//对向量排序
开始=时钟();
排序(myvec.begin(),myvec.end());
停止=时钟();
CUT< P>我不是C++程序员,但我的理解是:代码> STD::vector < /C> >与代码> STD::列表不同的性能特征。具体而言(如评论所述):
std::vector
有O(1)个随机访问,而std::list
没有
来自(我确信有不太粗略的参考,请随意插话):
向量机擅长:
- 通过位置索引(恒定时间)访问单个元素
- 以任意顺序(线性时间)迭代元素
- 从末尾添加和删除元素(固定摊销时间)
:
…列出容器的优点:
- 高效地插入和移除容器中任何位置的元素(恒定时间)
- 在容器内或不同容器之间高效移动元素和元素块(恒定时间)
- 按正向或反向顺序(线性时间)迭代元素
向量比列表在内存中的位置更近。这将在排序过程中产生更友好的缓存访问模式。向量将允许恒定时间元素交换以及恒定时间随机访问。列表需要线性时间进行随机访问,而指针更新交换的开销(可能)要大一些。我猜这类人正在做一系列的掉期交易。此外,向量在内存中移动自身的大部分时更有效
我很好奇,由于指针开销稍小,交换slist是否会比交换list快。不astd::vector
不使用合并排序(在大多数实现中,标准没有指定算法)
std::list
没有O(1)随机访问,因此它不能使用像Quick sort*这样的算法,这要求O(1)随机访问是快速的(这也是为什么std::sort
在std::list
上不起作用的原因)
在这种情况下,您必须使用前向迭代已经足够的算法,例如合并排序**
合并排序通常较慢
另见:
*:libstdc++实际上使用introsort。
**:libstdc++实际上在向量上使用了list::sort
和std::sort
但不使用相同的算法
std::sort
使用需要随机访问迭代器的排序算法,例如std::vector
所需的迭代器,而不是std::list
所需的迭代器
list::sort
专门用于列表;它通常实现合并排序,不需要随机访问
两种算法的比较总数都是O(n logn)(我说,在不知道编译器的std::sort
实现使用的确切算法的情况下)。
交换的总数也是O(n log n),但对于std::sort
,这意味着O(n log n)调用复制构造函数/赋值运算符,而对于list::sort
,这是一个指针操作。你的结构太小,这一优势无法实现。
我假设,只要您将具有非平凡副本构造函数的内容放入结构中(可能一个std::string
就足够了),std::list
就会获胜
编辑:在我的机器(x86_64-linux,gcc 4.6.2)上,一个用随机双精度转换为文本的std::string成员的初始化值似乎接近盈亏平衡点。你很接近:std::vector
有O(1)个随机访问,而std::list
没有(它是一个双链接列表)。可能值得注意的是,vector
和list
在后面迭代和插入项目的时间都是恒定的,vector
的常数较小。这并不能完全解决排序问题。对列表进行排序不使用随机访问,理论上的好处是不需要交换值。-不过,使用随机访问可以实现更好的排序算法?@UncleBens:使用随机访问进行排序要快得多。另外,链表的缓存行为非常糟糕。@DeadMG:不完全令人信服。这还取决于您正在排序的对象的类型:。而list::sort仍然是O(n logn),即使对于可以廉价交换的类型来说可能会有点糟糕。这不仅仅是内存效率。我同意。但这是一个巨大的事实