隨機排列生成演算法的一些隨想

2021-06-08 07:55:13 字數 2427 閱讀 2614

這篇文章主要是乙個閒文。如果您正在尋求乙個理想的隨機排列生成演算法,直接閱讀方法3,或是直接使用stl裡提供的random_shuffle()方法

另外請注意,這裡所討論的演算法並不是新的。

什麼是隨機排列?

乙個隨機排列是一組位於隨機位置的物件。

給定乙個物件,1, 2, 3 ... n,隨機排列看起來就是,

p1, p2, p3 ... pn

其中px是從原來的物件集合中選取的隨機值。

隨機排列對於撲克牌洗牌,隨機產生益智遊戲,產生隨機序列,或者生成乙個隨機子集合集(從 n 個物件中隨機選出 k 個物件),非常有用。

隨機排列生成演算法從天真到成熟,我的真實經驗

為了解釋演算法,我會用乙個輔助函式來產生隨機數。

int random(int min, int max);

其結果是乙個大於或等於 min 且小於 max 的乙個隨機數。

也就是說,結果是位於左閉右開區間內。

方法1,天真的方式

在隨機位置交換兩個元素。重複足夠的次數。

偽**:

cpp**  

array data(1..n);  

for(enough iterations)   

這種方法非常直觀,很簡單,它真的有效,前提是有足夠的迭代,比如對10個元素迭代100次。沒錯,它真的可以工作,我用過很多次。

但最大的問題是,迭代次數要遠遠高於物件數(n),因為在兩次中選擇相同位置的兩個元素的概率是相當大的,概率為1 /(n * n)相當的高。

因此,用這種方法,我們要麼得到糟糕的效能(使用非常高的迭代),要麼是比較差的隨機性(低迭代)。

方法2,從籃子裡取小球

假設所有的物件都是球。我們把所有的球到乙個籃子,然後從籃子裡隨機拿出乙個球,如是重複直到籃子變空。

偽**:

cpp**  

array data(1..n);  

basket = new

array;  

for(i = 0 to n - 1)   

for(i = 0 to n - 1)   

這種方法也很直觀,因為在現實中,彩票**正是用這種方法,而且用的是真正的籃子和球。

而且這種方法效能很好,具有o(n)的時間複雜度。

理論上,其結果是能保證足夠隨機的,因為所有的球是從籃子裡隨機選擇。

方法3,演進 - 在籃球裡原地選擇

第二種方法是很好的實現,而且很容易操作。但是,在計算機世界中,它有乙個缺點:它需要乙個額外的臨時緩衝區來作為籃子。

在大多數情況下這沒什麼,不是個問題,但我們是否可以做得更好呢?

當然可以!我們可以在就在籃子裡選擇。

實際的 c++ **:

cpp**  

intrandom(

intminvalue, 

intmaxvalue)  

else

}  template

<

typename

t>  

void

randompermutation(t & data, 

intcount)  

}  c 版本的非模板randompermutation(用你需要的資料型別替換 "int" ,並自行實現 swap 函式)

cpp**  

void

randompermutation(

int* data, 

intcount)  

}  上面的**正是籃子方法的實現,不過比較隱晦。

了解原理

讓我們假設籃子是有n個槽的長形籃子。則籃子是線性的。

那麼初始籃子的樣子,

1,2,3,4,5,6,...,n

現在假設我們隨機選擇5,那麼籃子裡的樣子,

1,2,3,4,e,6,...,n

e表示空的槽。

接下來我們不刪除e,我們把 5 之前的所有槽向後移動乙個位置,並把 5 放在第乙個槽裡

5,1,2,3,4,6,...,n

下次如果我們選擇3,我們只是移動 3 之前 5 之後的所有槽,然後把3個在那裡,

5,3,1,2,4,6,...,n

重複n次

很好,是嗎?我們不需要乙個額外的緩衝區。但是,我們必須移動很多槽,不好玩。

如果第 c 次選擇,我們只是把候選的元素與第 c 個元素交換,怎麼樣?

上面的迭代會進行以下變化,

1, 2, 3, 4, 5, 6, ..., n // 初始

5, 2, 3, 4, 1, 6, ..., n // 隨機選擇 5, 和 1 交換

5, 3, 2, 4, 1, 6, ..., n // 隨機選擇 3, 和 2 交換

這正是上面**做的事情。

全排列生成演算法(一)

對於給定的集合a,其中的n個元素互不相同,如何輸出這n個元素的所有排列 全排列 這裡以a為例,來說明全排列的生成方法,對於這個集合,其包含3個元素,所有的排列情況有3 6種,對於每一種排列,其第乙個元素有3種選擇a,b,c,對於第乙個元素為a的排列,其第二個元素有2種選擇b,c 第乙個元素為b的排列...

一種隨機數生成演算法

隨機數生成類 class randnumber randnumber randnumber unsigned long s 0 else unsigned short randnumber random unsigned long n double randnumber frandom unsign...

隨機數生成演算法的研究

摘 要 本文通過流程圖和實際例程,較詳細地闡述了隨機數生成的演算法和具體的程式設計,分析了其符合演算法特徵的特性。1引言 在 資料結構 演算法分析與設計 科學模擬等方面都需要用到隨機數。由於在數學上,整數是離散型的,實數是連續型的,而在某一具體的工程技術應用中,可能還有數 據值的範圍性和是否可重複性...