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随机排列(请参阅)。总而言之,我的代码在列表中执行以下步骤:

  • 循环浏览
    列表的每个元素
  • 从当前位置开始,使用随机选择的元素交换该元素,包括其本身
  • 因为列表不提供随机访问,这意味着我在步骤1中迭代整个列表,对于每个元素,我将再次迭代,从该点开始,平均超过剩余元素的一半。这是我的程序性能的一个主要瓶颈,所以我希望改进它。出于其他原因,我需要继续使用
    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