两种洗牌算法:
1、Fisher-Yates
2、Knuth
type Handle struct {
}
Fisher–Yates 洗牌算法
// Fisher-Yates正向
func (h *Handle) shuffle_FisherYates_Forward(cards []uint32, r *rand.Rand) {
var size int = len(cards)
var j int = 0
for i, _ := range cards {
j = r.Intn(size-i) + i
cards[i], cards[j] = cards[j], cards[i]
}
}
// Fisher-Yates反向
func (h *Handle) shuffle_FisherYates_Reverse(cards []uint32, r *rand.Rand) {
var size int = len(cards)
var j int = 0
for i := size - 1; i > 0; i-- {
j = r.Intn(i + 1)
cards[i], cards[j] = cards[j], cards[i]
}
}
Knuth洗牌算法
// 第一步:为每张牌生成一个随机数
// 第二步:按这个随机数进行排序
type Knuth struct {
index int
ran int
}
func (h *Handle) shuffle_Knuth(cards []uint32, r *rand.Rand){
l := len(cards)
tmp := make([]uint32, l)
rands := make([]Knuth, l)
for i := 0; i < l; i++{
rands[i] = Knuth{index:i, ran:r.Intn(l)}
tmp[i] = cards[i]
}
BubbleSort(rands)
for i,v := range rands{
cards[i] = tmp[v.index]
}
}
// 冒泡排序
func BubbleSort(arr []Knuth) []Knuth {
num := len(arr)
for i := 0; i < num; i++ {
status := false
for j := i + 1; j < num; j++ {
if arr[i].ran > arr[j].ran {
status = true
arr[i], arr[j] = arr[j], arr[i]
}
}
if status == false {
break
}
}
return arr
}
入参解释
1、cards []uint32 // 即将要洗的牌
2、r *rand.Rand // 随机方式
生成方式:var r *rand.Rand = rand.New(rand.NewSource(“一个64位的随机种子”)
随机种子的选择建议:由于实际情况下,多机器运行速率很快,可能导致并发的时候,生成的纳秒种子可能多次相同。所以建议种子由snowflake算法生成唯一性。
个人眼界有限,如果有什么好的洗牌算法,希望大家留言~~