shuffle算法,我把它叫做洗牌算法因为他和我们洗扑克牌的方式很像,它的目标正好与各种的sort算法相反,即把一个有序(或者无序)的一系列元素打乱,以满足需求。
如果你是python或者ruby程序员可能你觉得很简单,因为他们在语言层面上实现了很多很方便的函数,然而Go语言要想打乱数组或者切片中数据的顺序,需要自己实现的。
Ruby中有一个叫shuffle的方法:
1
2
|
array
=
[
1
,
2
,
3
,
4
,
5
]
array
.
shuffle
# shuffles the array!
|
Python也同样非常的简单:
1
2
3
|
import
random
array
=
[
1
,
2
,
3
,
4
,
5
]
random
.
shuffle
(
array
)
# shuffles the array!
|
简单粗暴 – 创建新的数组或者切片
1
2
3
4
5
6
7
8
9
10
11
|
func
Shuffle
(
vals
[
]
int
)
[
]
int
{
r
:
=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
(
)
.
Unix
(
)
)
)
ret
:
=
make
(
[
]
int
,
len
(
vals
)
)
n
:
=
len
(
vals
)
for
i
:
=
0
;
i
<
n
;
i
++
{
randIndex
:
=
r
.
Intn
(
len
(
vals
)
)
ret
[
i
]
=
vals
[
randIndex
]
vals
=
append
(
vals
[
:
randIndex
]
,
vals
[
randIndex
+
1
:
]
.
.
.
)
}
return
ret
}
|
其实我们可以用rand.Perm() 更为高效的实现
1
2
3
4
5
6
7
8
9
|
func
Shuffle
(
vals
[
]
int
)
[
]
int
{
r
:
=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
(
)
.
Unix
(
)
)
)
ret
:
=
make
(
[
]
int
,
len
(
vals
)
)
perm
:
=
r
.
Perm
(
len
(
vals
)
)
for
i
,
randIndex
:
=
range
perm
{
ret
[
i
]
=
vals
[
randIndex
]
}
return
ret
}
|
无需创建新的数组或者切片来实现洗牌算法
1
2
3
4
5
6
7
8
|
func
main
(
)
{
vals
:
=
[
]
int
{
10
,
12
,
14
,
16
,
18
,
20
}
r
:
=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
(
)
.
Unix
(
)
)
)
for
_
,
i
:
=
range
r
.
Perm
(
len
(
vals
)
)
{
val
:
=
vals
[
i
]
fmt
.
Println
(
val
)
}
}
|
运行后发现你可以看到返回的数据已经被打乱了。
如果一个你使用的是切片且不知道切片的大小和容量,且不修改值传递的值,那么我们可以这么做。
1
2
3
4
5
6
7
8
9
|
func
Shuffle
(
vals
[
]
int
)
{
r
:
=
rand
.
New
(
rand
.
NewSource
(
time
.
Now
(
)
.
Unix
(
)
)
)
for
len
(
vals
)
>
0
{
n
:
=
len
(
vals
)
randIndex
:
=
r
.
Intn
(
n
)
vals
[
n
-
1
]
,
vals
[
randIndex
]
=
vals
[
randIndex
]
,
vals
[
n
-
1
]
vals
=
vals
[
:
n
-
1
]
}
}
|