排序列表和结构向量之间的性能差距。C++; 我编写了一个简单的C++代码,检查排序数据的速度,以列表的形式表示,然后用向量表示。p>

排序列表和结构向量之间的性能差距。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.

对于列表,我得到的时间是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;
结构粒子
{
双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快。

不a
std::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),即使对于可以廉价交换的类型来说可能会有点糟糕。这不仅仅是内存效率。我同意。但这是一个巨大的事实