回答
将Fisher-Yates shuffle修改为不对数组中10%的指数做任何事情。
这是我发布(来自维基百科)和修改的java代码,但我认为你可以将它翻译成C++,因为这更像是一个算法问题而不是语言问题。
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;
}
}
这并不能保证10%的数组将被混洗,因为if(rng.nextDouble()<0.1)继续存在随机性。 – 2009-11-03 14:42:31
正确。这可以让你大约90%的数组混洗。也许那么最好是将所有数组索引列表进行混洗,如果当前索引位于该混洗索引数组的前10%,则调用continue。 – 2009-11-03 14:48:55
我同意这会更好 – 2009-11-03 14:54:29
单程可使用,性病:: random_shuffle(),通过控制输入范围控制%....
为什么不执行随机选择的位置处,其中,N由下式确定N个互换百分比?
因此,如果我有100个元素,10%洗牌将执行10次交换。每次交换随机选取数组中的两个元素并切换它们。
这可能不会给所有你想要的各种混洗提供一致的概率。 – 2009-11-03 14:40:10
@kbloom:你说的“你想要的各种洗牌”是什么意思?我们都知道洗牌是什么。什么是10%洗牌? 10%的元素有可能改变位置的洗牌?一个洗牌哪里有10%的元素改变了位置?对阵列的约10%进行全面洗牌,无论是预定义还是随机挑选?有很多这样的事情:给定一个圆圈中的随机和弦,它的长度大于等边三角形的一条腿的概率是多少?这是一半,或三分之一,或四分之一。 – 2009-11-03 15:07:27
您可以使用shuffle bag算法来选择数组的10%。然后在该选择上使用正常的随机播放。
如何编写自己的随机迭代器,并使用random_shuffle,这样的事情:(没有经过充分测试,只是为了得到一个想法)
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;
}
我认为最优雅的解决方案......但我肯定会使用一些Boost.Iterators来缓解对所有锅炉代码的需求。 – 2009-11-04 07:45:48
你可以试试这个:
分配一个随机数矢量的每个元素。随机数在您指定的随机数中最小的10%随机数进行随机播放:您甚至可以想象用占位符替换向量中的10%,然后根据其随机数对10%进行排序,然后将它们插入矢量占位符的地方。
如果你有SGI的std::random_sample
扩展名,你可以这样做。如果不是,那么在一个函数之上实现random_sample
很容易,该函数返回指定范围内的均匀分布的随机整数(Knuth,第2卷,“算法R”)。
#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]];
}
}
不是最有效的,因为它使用三个“小”的载体,但避免了必须适应费 - 耶茨算法来对向量的一个子集进行操作。在实践中,你可能希望这是一个在一对随机访问迭代器而不是向量上运行的函数模板。我没有这样做,因为我认为它会混淆代码,而你没有要求。我也会采取一个大小,而不是一个比例,留给呼叫者决定如何将分数舍入。
- 1. 洗牌的随机化
- 2. 洗牌.txt文件随机
- 3. 无法随机洗牌
- 4. 随机洗牌数组
- 5. N-Puzzle伪随机洗牌?
- 6. 随机洗牌在PHP?
- 7. 随机随机洗牌C++数组(每次不同)
- 8. 创建一个部分洗牌的随机数排序列表
- 9. 随机随机洗牌列表变为无
- 10. 洗牌列表中随机的Java
- 11. 如何在Python中进行随机但部分洗牌?
- 12. 随机洗牌和函数指针
- 13. 从资源随机洗牌文本
- 14. 随机洗牌错误信息
- 15. 随机分区与分区然后洗牌
- 16. 需要使用密钥的可重复的随机数组随机洗牌
- 17. 如何实现随机 - 但不是太随机的重复洗牌
- 18. 施加一个随机变量随机
- 19. IEnumerable的洗牌不是随机的一套集
- 20. 张量流随机洗牌队列:元素不足
- 21. 创造可赢得的“随机”单人纸牌洗牌
- 22. C++中的Gamma分布随机变量
- 23. 向量push_back随机发生
- 24. MATLAB - 生成随机向量
- 25. 元随机重定向随机X秒
- 26. 随机化阵列的一部分
- 27. 分配随机数变量
- 28. 随机分割故障C++
- 29. C#随机数是不是“随机”
- 30. 随机洗牌相同元素的排序比较方法
你需要精确的概率属性吗?答案取决于它。 – 2009-11-03 15:03:30