一、背景
数组乱序指的将数组的每一个元素随机打乱,并且对于每一个元素而言,它被放置到每一个位置的概率都相等。
有很多算法都能实现这个要求,其中Knuth-Durstenfeld Shuffle算法性能较高,其时间复杂度为O(n),空间复杂度为O(1),实现也简单一些,这里给出算法的原理以及C++、C#、JS程序。
二、Knuth-Durstenfeld Shuffle算法
其算法原理具体如下:
- 已知一个数组a,元素个数为N,其索引为0~N-1;
- 令i = N - 1;
- 生成随机数index,区间为[0, i];
- 交换a[i]与a[index];
- 如果i > 0,则i = i - 1并跳转到步骤3;
- 结束。
三、程序
C++
#include <time.h>
#include <stdlib.h>
#include <utility>
template <class T, size_t Len>
void Shuffle(T (&a)[Len]) {
srand(time(NULL));
for (size_t i = Len - 1; i > 0; i--) {
size_t index = rand() % (i + 1);
std::swap(a[i], a[index]);
}
}
int main() {
int a[] = {1, 2, 3, 4, 5};
Shuffle(a);
return 0;
}
C#
public static void Shuffle<T>(T[] a) {
Random rnd = new Random();
for (int i = a.Length - 1; i > 0; i--) {
int index = rnd.Next(i + 1);
T temp = a[i];
a[i] = a[index];
a[index] = temp;
}
}
public static void Main() {
int[] a = new[] {1, 2, 3, 4, 5};
Shuffle(a);
}
JavaScript
function shuffle(a) {
for (let i = a.length - 1; i > 0; i--) {
let index = Math.random() * (i + 1) | 0;
[a[i], a[index]] = [a[index], a[i]];
}
}
a = [1, 2, 3, 4, 5];
shuffle(a);