C++ 随机化std::列表时提高性能
我有一个C++ 随机化std::列表时提高性能,c++,performance,list,random,std,C++,Performance,List,Random,Std,我有一个std::list,我目前正在使用Fisher-Yates随机排列(请参阅)。总而言之,我的代码在列表中执行以下步骤: 循环浏览列表的每个元素 从当前位置开始,使用随机选择的元素交换该元素,包括其本身 因为列表不提供随机访问,这意味着我在步骤1中迭代整个列表,对于每个元素,我将再次迭代,从该点开始,平均超过剩余元素的一半。这是我的程序性能的一个主要瓶颈,所以我希望改进它。出于其他原因,我需要继续使用list作为容器,但我正在考虑在随机函数开始时转换为vector,然后在最后转换回list
std::list
,我目前正在使用Fisher-Yates随机排列(请参阅)。总而言之,我的代码在列表中执行以下步骤:
列表的每个元素
list
作为容器,但我正在考虑在随机函数开始时转换为vector
,然后在最后转换回list
。我的列表通常包含300-400个项目,因此我认为容器之间的转换成本是值得的,以避免按顺序遍历这些项目
我的问题是:这似乎是优化代码的最佳方式吗?有更好的方法吗?一个简单的改进是将数据复制到一个向量中,洗牌该向量,然后将其复制回列表中。这就是Max和PeskyGnat在评论中提出的建议:
vector<int> myVector(myList.size());
copy(myList.begin(), myList.end(), myVector.begin());
random_shuffle(myVector.begin(), myVector.end());
list<int> myListShuffled(myVector.begin(), myVector.end());
vector myVector(myList.size());
复制(myList.begin(),myList.end(),myVector.begin());
随机洗牌(myVector.begin(),myVector.end());
列出myListShuffled(myVector.begin(),myVector.end());
这个实现相当快。但是,它将在向量上执行三次传递,您可以通过自己实现shuffle将其简化为两次传递:
vector<int> myVector(myList.size());
int lastPos = 0;
for(list<int>::iterator it = myList.begin(); it != myList.end(); it++, lastPos++) {
int insertPos = rand() % (lastPos + 1);
if (insertPos < lastPos) {
myVector[lastPos] = myVector[insertPos];
}
myVector[insertPos] = *it;
}
list<int> myListShuffled(myVector.begin(), myVector.end());
vector myVector(myList.size());
int-lastPos=0;
for(list::iterator it=myList.begin();it!=myList.end();it++,lastPos++){
int insertPos=rand()%(lastPos+1);
如果(插入位置<最后位置){
myVector[lastPos]=myVector[insertPos];
}
myVector[insertPos]=*它;
}
列出myListShuffled(myVector.begin(),myVector.end());
因为第一个版本更容易理解,更不容易出错,所以它几乎总是更可取的。。。除非这段代码对您的性能至关重要(并且您通过测量确认了这一点)
编辑:顺便说一句,由于您正在阅读维基百科文章,第二个代码示例使用了Fisher Yates的“由内而外”变体。一个简单的改进是将数据复制到向量中,将向量洗牌,然后将其复制回列表中。这就是Max和PeskyGnat在评论中提出的建议:
vector<int> myVector(myList.size());
copy(myList.begin(), myList.end(), myVector.begin());
random_shuffle(myVector.begin(), myVector.end());
list<int> myListShuffled(myVector.begin(), myVector.end());
vector myVector(myList.size());
复制(myList.begin(),myList.end(),myVector.begin());
随机洗牌(myVector.begin(),myVector.end());
列出myListShuffled(myVector.begin(),myVector.end());
这个实现相当快。但是,它将在向量上执行三次传递,您可以通过自己实现shuffle将其简化为两次传递:
vector<int> myVector(myList.size());
int lastPos = 0;
for(list<int>::iterator it = myList.begin(); it != myList.end(); it++, lastPos++) {
int insertPos = rand() % (lastPos + 1);
if (insertPos < lastPos) {
myVector[lastPos] = myVector[insertPos];
}
myVector[insertPos] = *it;
}
list<int> myListShuffled(myVector.begin(), myVector.end());
vector myVector(myList.size());
int-lastPos=0;
for(list::iterator it=myList.begin();it!=myList.end();it++,lastPos++){
int insertPos=rand()%(lastPos+1);
如果(插入位置<最后位置){
myVector[lastPos]=myVector[insertPos];
}
myVector[insertPos]=*它;
}
列出myListShuffled(myVector.begin(),myVector.end());
因为第一个版本更容易理解,更不容易出错,所以它几乎总是更可取的。。。除非这段代码对您的性能至关重要(并且您通过测量确认了这一点)
编辑:顺便说一句,由于您正在阅读维基百科文章,第二个代码示例使用了Fisher-Yates的“由内而外”变体。显示代码本身比描述代码的功能更有用。与std::Vector相比,交换std::list元素的成本更高。在进行交换之前,尝试将列表复制到一个向量(简单),看看它是否能改善情况。也许可以选择使用deque?它支持列表和向量语义,因此您可以使用STL中的random_shuffle显示代码本身比描述代码的功能更有用。与std::vectors相比,交换std::list元素的成本更高。在进行交换之前,尝试将列表复制到一个向量(简单),看看它是否能改善情况。也许可以选择使用deque?它支持列表和向量语义,因此您可以从STL中使用random_shuffle