洗牌程式的兩種實現方法比較

2022-02-24 09:13:09 字數 1715 閱讀 8036

首先,我介紹一種很常見的方法:隨機生成法(我自己命名的),這方法我在掃雷遊戲中隨機分布雷的位置時用過(思想是一樣的),該方法要點就是從頭開始逐個隨機生成規定區域的數字,如果新生成隨機數之前已經生成過就不儲存該數;如果新生成的隨機數之前沒有生成過就儲存該數;直到生成的數字的數量達到所需的數量。

實現**如下:

size_t shuffle(char s, int

n) }

returnt;}

void printcards(char s, int

n) cout

<

}

**中使用了memchr函式(時間複雜度可能是o(n),沒找到依據),即使是o(1),它的迴圈生成隨機數的次數是不固定的(大於等於需要生成的個數)。

實現**:

void swap(int& a, int&b)

size_t shuffle2(

int s, int

n)

for (int i=0; i)

}returnt;}

void printcards2(int s, int

n) cout

<

}

比較:在時間上方法二比方法一快好多,因為交換位置的次數的最大值是限定了的(生成隨機數的次數是固定的),而且省去了查詢新生成數是否在已生成數中的時間。方法一中,當新生成的數在已生成的數中就需要從新生成乙個隨機數,從而隨機生成數的次數是不固定的(有最小值)。

測試**:

#include #include 

#include

#include

using

namespace

std;

const

int cards_count=54;

int

main()

else

}return0;

}

結果:

我還是不能確定第二種方法是不是更好的,因為是自己想到的,我的驗證也不是很完善,也許有什麼其他的缺點(比如說隨機性太弱),也沒在其他書上看到過,如果網友們在哪看到過就告訴下我吧,方法一是在《c和c++**精粹》中文版p97中找到的。

後續補充:

謝謝chncwang的回覆,方法二不是完全隨機的,完全隨機的修改如下:

size_t shuffle22(int s, int

n)

for (int i=n-1; i>0; --i)

}return

t;}

因為"第1次移動後,第1個數還在第1個位置的概率是1/n,後續移動只會減少這個概率。所以這個演算法不是完全隨機的"。修改後的演算法其實就是使用c++的stl庫中的random_shuffle()函式的實現方法。取隨機數的時候的範圍每次都隨著i的改變而變動,這樣就不會減少之前的位置的數還是原來的數的概率了(即後續交換操作不會影響到已經交換過的位置)。

使用標準庫中的random_shuffle()函式實現很簡單,**如下:

洗牌程式的兩種實現方法比較

size t shuffle22 int s,int n for int i n 1 i 0 i return t 因為 第1次移動後,第1個數還在第1個位置的概率是1 n,後續移動只會減少這個概率。所以這個演算法不是完全隨機的 修改後的演算法其實就是使用c 的stl庫中的random shuffl...

兩種洗牌演算法比較

演算法1原理 1.用乙個整型陣列記錄各個位置是否已經放置了數,如果放置了則不為0,否則為0。所以在演算法開始的時候,初始化此陣列每個元素的值都為0.2.每次產生乙個0 53之間的數,看這個位置是否放置了數,如果已經放置了,則繼續採用同樣的方法找乙個隨機的位置進行判斷,如果這個位置還未放置,則設定此位...

TreeSet兩種自然比較方法

一 1.用treeset集合儲存自定義物件,無參構造方法使用的是自然排序對元素進行排序的自然排序,2.就是讓元素所屬的類實現comparable介面,重寫compareto t o 方法 3.重寫方法時,一定要注意排序規則必須按照要求的主要條件和次要條件來寫 public class student...