https://github.com/golang-infrastructure/go-shuffle
提供几种洗牌算法的Go实现
https://github.com/golang-infrastructure/go-shuffle
go golang shuffle
Last synced: 5 months ago
JSON representation
提供几种洗牌算法的Go实现
- Host: GitHub
- URL: https://github.com/golang-infrastructure/go-shuffle
- Owner: golang-infrastructure
- License: mit
- Created: 2022-10-26T14:26:26.000Z (almost 3 years ago)
- Default Branch: main
- Last Pushed: 2023-02-28T16:34:03.000Z (over 2 years ago)
- Last Synced: 2025-03-31T10:39:00.905Z (6 months ago)
- Topics: go, golang, shuffle
- Language: Go
- Homepage:
- Size: 16.6 KB
- Stars: 4
- Watchers: 1
- Forks: 2
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[English Document](./README_English.md)
[中文文档](./README.md)
# 洗牌算法(Shuffle Algorithm)
# 一、支持的洗牌算法
洗牌算法的定义:为有限集合生成随机排序的算法。
目前支持的洗牌算法:
- Fisher–Yates-Knuth
- Scatology# 二、安装
```bash
go get -u github.com/golang-infrastructure/go-shuffle
```# 三、API代码示例
## 3.1 对切片shuffle
```go
package mainimport (
"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 mainimport (
"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)`,不再展开详解。