C++ c++;向量随机洗牌的一部分

C++ c++;向量随机洗牌的一部分,c++,vector,shuffle,C++,Vector,Shuffle,在向量中洗牌一定百分比的元素的最佳方式是什么 假设我想要10%或90%的向量被洗牌。 不一定是前10%,但总体而言只有10% TIA可以使用std::random_shuffle()一种方式,通过控制输入范围来控制%。为什么不对随机选择的位置执行N次交换,其中N由百分比决定 所以如果我有100个元素,10%的洗牌将执行10次交换。每次交换都会随机选取数组中的两个元素并进行切换。修改Fisher-Yates洗牌,使其对数组中10%的索引不做任何操作 这是我从维基百科发布的java代码,并进行修改,

在向量中洗牌一定百分比的元素的最佳方式是什么

假设我想要10%或90%的向量被洗牌。 不一定是前10%,但总体而言只有10%


TIA可以使用std::random_shuffle()一种方式,通过控制输入范围来控制%。

为什么不对随机选择的位置执行N次交换,其中N由百分比决定


所以如果我有100个元素,10%的洗牌将执行10次交换。每次交换都会随机选取数组中的两个元素并进行切换。

修改Fisher-Yates洗牌,使其对数组中10%的索引不做任何操作

这是我从维基百科发布的java代码,并进行修改,但是我认为你可以把C++翻译成C++,因为这是一个比语言问题更为复杂的算法问题。p>

public static void shuffleNinetyPercent(int[] array) 
{
    Random rng = new Random();       // java.util.Random.
    int n = array.length;            // The number of items left to shuffle (loop invariant).
    while (n > 1) 
    {
        n--;                         // n is now the last pertinent index
        if (rng.nextDouble() < 0.1) continue; //<-- ADD THIS LINE
        int k = rng.nextInt(n + 1);  // 0 <= k <= n.
        // Simple swap of variables
        int tmp = array[k];
        array[k] = array[n];
        array[n] = tmp;
    }
}
publicstaticvoidshufflenEntityPercent(int[]数组)
{
Random rng=new Random();//java.util.Random。
int n=array.length;//要洗牌的项目数(循环不变)。
而(n>1)
{
n--;//n现在是最后一个相关索引

如果(rng.nextDouble()<0.1)继续;//您可以使用随机分组算法选择10%的数组。然后对该选择使用普通随机分组。

如何编写您自己的随机迭代器并使用随机分组,类似这样的方法:(完全未经测试,只是想了解一下)

模板
类myRandomIterator:public std::iterator
{
公众:
myRandomIterator(std::vector&vec,size\u t pos=0):myVec(vec),myIndex(0),myPos(pos)
{
srand(时间(空));
}
布尔运算符==(常量myRandomIterator&rhs)常量
{
返回myPos==rhs.myPos;
}
布尔运算符!=(常量myRandomIterator&rhs)常量
{
返回!(myPos==rhs.myPos);
}
bool操作符您可以尝试以下方法:

为向量的每个元素分配一个随机数。将随机数在所分配的随机数中最小的10%中的元素洗牌:你甚至可以想象用占位符替换向量中的10%,然后根据它们的随机数对10%进行排序,并将它们插入到占位符所在的向量中re.

如果你有SGI的扩展,你可以这样做。如果没有,很容易在返回指定范围内均匀分布的随机整数的函数上实现
random\u sample
(Knuth,第2卷,“算法R”)

#包括
#包括
使用std::vector;
无效随机分数(向量和数据,双分数){

assert(fraction>=0.0&&fraction这可能不会为所有您想要的各种洗牌提供统一的概率。@kbloom:您所说的“所有您想要的各种洗牌”是什么意思?我们都知道什么是洗牌。什么是10%洗牌?10%的元素有可能改变位置的洗牌?10%的元素有可能改变位置的洗牌?10%的元素有可能改变位置的洗牌?整个数组的10%洗牌,无论是预定义的还是随机挑选的?有很多类似的事情:给定一个圆圈中的随机和弦,w它比内接等边三角形的一条腿长的概率是多少?它是二分之一、三分之一或四分之一。这并不保证10%的数组会被洗牌,因为
if(rng.nextDouble()<0.1)中的随机性继续
正确。这将使您得到大约90%的数组被洗牌。也许最好洗牌所有数组索引的列表,然后如果当前索引位于被洗牌的索引数组的前10%中,则调用continue。您是否需要精确的概率属性?答案取决于此。我认为最优雅的解决方案是我肯定会使用一些Boost.迭代器来减少对所有锅炉板代码的需求。
template<class T>
class myRandomIterator : public std::iterator<std::random_access_iterator_tag, T>
{
public:
    myRandomIterator(std::vector<T>& vec, size_t pos = 0): myVec(vec), myIndex(0), myPos(pos)
    {
        srand(time(NULL));
    }

    bool operator==(const myRandomIterator& rhs) const
    {
        return myPos == rhs.myPos;
    }

    bool operator!=(const myRandomIterator& rhs) const
    {
        return ! (myPos == rhs.myPos);
    }

    bool operator<(const myRandomIterator& rhs) const
    {
        return myPos < rhs.myPos;
    }

    myRandomIterator& operator++() 
    {
        ++myPos;
        return fill();
    }

    myRandomIterator& operator++(int) 
    {
        ++myPos;
        return fill();
    }

    myRandomIterator& operator--() 
    {
        --myPos;
        return fill();
    }

    myRandomIterator& operator--(int)
    {
        --myPos;
        return fill();
    }



    myRandomIterator& operator+(size_t n) 
    {
        ++myPos;
        return fill();
    }

    myRandomIterator& operator-(size_t n) 
    {
        --myPos;
        return fill();
    }


    const T& operator*() const
    {
        return myVec[myIndex];
    }

    T& operator*()
    {
        return myVec[myIndex];
    }



private:
    myRandomIterator& fill()
    {
        myIndex = rand() % myVec.size();
        return *this;
    }

private:
    size_t myIndex;
    std::vector<T>& myVec;
    size_t myPos;

};

int main()
{
    std::vector<int> a;
    for(int i = 0; i < 100; ++i)
    {
        a.push_back(i);
    }

    myRandomIterator<int> begin(a);
    myRandomIterator<int> end(a, a.size() * 0.4);

    std::random_shuffle(begin, end);

    return 0;
}
#include <algorithm>
#include <vector>
using std::vector;

void shuffle_fraction(vector<int> &data, double fraction) {
    assert(fraction >= 0.0 && fraction <= 1.0);

    // randomly choose the indices to be shuffled
    vector<int> bag(data.size());
    for(int i = 0; i < bag.size(); ++i) bag[i] = i;

    vector<int> selected(static_cast<int>(data.size() * fraction));
    std::random_sample(bag.begin(), bag.end(), selected.begin(), selected.end());

    // take a copy of the values being shuffled
    vector<int> old_value(selected.size());
    for (int i = 0; i < selected.size(); ++i) {
        old_value[i] = data[selected[i]];
    }

    // choose a new order for the selected indices
    vector<int> shuffled(selected);
    std::random_shuffle(shuffled.begin(), shuffled.end());

    // apply the shuffle to the data: each of the selected indices
    // is replaced by the value for the corresponding shuffled indices
    for (int i = 0; i < selected.size(); ++i) {
        data[selected[i]] = old_value[shuffled[i]];
    }
}