随机化std :: list时提高性能

时间:2012-04-17 13:42:34

标签: c++ performance list random std

我有一个std::list我目前正在使用Fisher-Yates shuffle随机化(请参阅http://en.wikipedia.org/wiki/Fisher-Yates_shuffle)。总而言之,我的代码在列表中执行以下步骤:

  1. 循环遍历list
  2. 的每个元素
  3. 使用随机选择的元素从当前位置开始交换元素,包括其自身。
  4. 因为列表不提供随机访问,这意味着我在步骤1中迭代整个列表,并且对于我再次迭代的每个元素,平均超过该点之后剩余元素的一半。这是我的程序性能的一个主要瓶颈,所以我希望改进它。出于其他原因,我需要继续使用list作为我的容器,但我正在考虑在随机化函数的开头转换为vector,然后转换回list。结束。我的列表通常包含300到400个项目,所以我猜想容器之间的转换成本是值得的,以避免顺序遍历项目。

    我的问题是:这似乎是优化代码的最佳方式吗?还有更好的方法吗?

1 个答案:

答案 0 :(得分:4)

一个简单的改进是将数据复制到矢量中,对矢量进行混洗,然后将其复制回列表中。这就是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());

这个实现非常快。但是,它将在向量上执行三次传递,并且您可以通过自己实施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());

由于第一个版本更易于理解且更不易出错,因此它几乎总是更可取......除非这些代码对您的性能至关重要(并且您通过测量确认了这一点)。

编辑:顺便说一句,既然您正在查看维基百科文章,那么第二个代码示例将使用&#34;由内到外&#34; Fisher-Yates的变体。

相关问题