洗牌算法就是给你一个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 2017-02-11 09:36  会飞的金鱼  阅读(149)  评论(0)    收藏  举报