go-shuffle 几种洗牌算法的Go实现 go-shuffle

CC11001100 • 2426 次点击    
这是一个分享于 的项目,其中的信息可能已经有所发展或是发生改变。
# 洗牌算法(Shuffle Algorithm) # 一、支持的洗牌算法 洗牌算法的定义:为有限集合生成随机排序的算法。 目前支持的洗牌算法: - Fisher–Yates-Knuth - Scatology # 二、安装 ```bash go get -u github.com/golang-infrastructure/go-shuffle ``` # 三、API代码示例 ## 3.1 对切片shuffle ```go package main import ( "fmt" "github.com/golang-infrastructure/go-shuffle" ) func main() { // 对切片中的元素shuffle slice := []int{1, 2, 3, 4, 5} shuffle.Shuffle(slice) fmt.Println(slice) // Output: // [5 1 2 3 4] } ``` ## 3.2 对矩阵shuffle ```go package main import ( "fmt" "github.com/golang-infrastructure/go-shuffle" ) func main() { // 对二维矩阵中的元素shuffle matrix := [][]int{ {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}, {11, 12, 13, 14, 15, 16, 17, 18, 19, 20}, {21, 22, 23, 24, 25, 26, 27, 28, 29, 30}, {31, 32, 33, 34, 35, 36, 37, 38, 39, 40}, } // 注意可能会返回错误,比如二维数组每行长度不一致则无法shuffle err := shuffle.ShuffleMatrix(matrix) if err != nil { fmt.Println("Shuffle matrix failed: " + err.Error()) return } fmt.Println(matrix) // Output: // [[11 40 6 23 15 28 4 7 37 21] [29 26 33 5 35 13 22 32 19 34] [31 30 36 20 2 10 24 39 9 27] [16 8 18 14 1 17 38 12 25 3]] } ``` # 四、Fisher–Yates-Knuth洗牌算法 假设现在有一个数组: ``` [1, 2, 3, 4, 5] ``` 从最右边的坐标`len(slice)-1`开始作为`right_index`,每次从`[0, right_index]`随机选择一个下标,将选中的下标的值与`right_index`交换,并将`right_index`减一往左偏移。 代码示例: ```go // 使用自己独立的随机数生成器,与其它的调用区分开 var standaloneRand = rand.New(rand.NewSource(time.Now().Unix())) // FisherYatesKnuthShuffle Fisher–Yates-Knuth Shuffle或 算法对一维数组洗牌,O(n) func FisherYatesKnuthShuffle[T any](slice []T) { for index := len(slice) - 1; index > 0; index-- { chooseIndex := standaloneRand.Intn(index + 1) slice[chooseIndex], slice[index] = slice[index], slice[chooseIndex] } } ``` 我们对上面的算法扩展一下,很容易就能得到矩阵的shuffle算法,将矩阵的每一行看做是拼接起来的一维数组,则将对矩阵进行shuffle的算法转换为了对切片shufle的算法,而对切片进行shuffle我们已经实现过了,API代码示例: ```go // FisherYatesShuffleMatrix Fisher–Yates-Knuth shuffle算法对矩阵洗牌 func FisherYatesShuffleMatrix[T any](matrix [][]T) error { // 参数检查 if err := check(matrix); err != nil { return err } row, col := len(matrix), len(matrix[0]) for index := row*col - 1; index > 0; index-- { chooseIndex := standaloneRand.Intn(index + 1) matrix[index/col][index%col], matrix[chooseIndex/col][chooseIndex%col] = matrix[chooseIndex/col][chooseIndex%col], matrix[index/col][index%col] } return nil } // 需要保证传入的二维数据是一个矩阵,否则后面可能会越界panic func check[T any](matrix [][]T) error { for i := 1; i < len(matrix); i++ { if len(matrix[i]) != len(matrix[i-1]) { return ErrMatrixUnavailable } } return nil } ``` # 五、Scatology算法 就是在Fisher–Yates-Knuth的基础上随机选择的时候不再选择最右边的`[0,right_index)`,不再展开详解。
授权协议:
开发语言:
Golang 查看源码»
2426 次点击  ∙  1 赞  
加入收藏 微博
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传