洗牌算法就是给你一个1到n的序列,让你随机打乱,保证每个数出现在任意位置的概率相同,也就是n!个的排列中,每一个排列出现的概率相同。
最常用的方法,每次随机选出一个没有被选过的数放到一个队列中,如果随机出来的数已经被选过,那么继续随机直到遇到一个没有被选过的数放入到队列中;重复这样的操作直到所有的数都被选择出来。
这种方法,第一个数选择有n个数可选,第2个数选择有(n-1)个数可选,其他的数选择类推,这样,最后选择出来的排列是n!的排列中的任意一个,显然是符合随机洗牌的要求的。由于这种方法每次随机选择一个数都有可能是之前的选过的数,需要再次随机。因此对选出一个数的随机平均情况下需要随机O(n)次,因此该方法的时间复杂度是O(n^2)。
最有效的方法是,当一个数被选之后,没有必要再下一次随机的时候再考虑它的,因此,每次只从可选的数的集合中进行随机,也就不用考虑是否会碰到已经选过的数了。这种算法的时间复杂度为O(n)。
算法的代码如下:
void Swap(int[] cards,int i,int j)
{
int temp=cards[i];
cards[i]=cards[j];
cards[j]=temp;
}
void Shuffle(int n)
{
int[] cards=new int[n];
for (int i = 1; i <= n; i++)
{
cards[i - 1] = i;
}
Console.WriteLine("洗牌之前的順序:");
for (int j = 1; j <= n; j++)
{
if (j % 10 == 0)
{
Console.WriteLine(cards[j - 1]);
}
else
{
Console.Write(cards[j - 1] + " ");
}
}
Random r=new Random();
for(int m=1;m<=n;m++)
{
Swap(cards,m-1,r.Next(0,n-1));
}
Console.WriteLine("洗牌之后的順序:");
for (int j = 1; j <= n; j++)
{
if (j % 10 == 0)
{
Console.WriteLine(i[j - 1]);
}
else
{
Console.Write(i[j - 1] + " ");
}
}
Console.ReadKey();
}
posted on
浙公网安备 33010602011771号