1、Fisher-Yates 洗牌算法
Fisher-Yates 洗牌算法是一种经典的高效算法,时间复杂度为 O(n)
,可以在数组中随机打乱元素。使用 rand()
函数和交换元素法。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int arr[], int n) {
for (int i = n - 1; i > 0; i--) {
int j = rand() % (i + 1); // 生成 [0, i] 之间的随机数
// 交换 arr[i] 和 arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int main() {
srand(time(0)); // 设置随机种子
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
shuffle(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
2、使用 rand() 函数和暴力法
通过两层循环随机交换数组中的元素。虽然它可以工作,但效率较低,时间复杂度为 O(n^2)
。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int arr[], int n) {
for (int i = 0; i < n; i++) {
int j = rand() % n; // 随机生成 0 到 n-1 之间的索引
// 交换 arr[i] 和 arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
int main() {
srand(time(0)); // 设置随机种子
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
shuffle(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}
3、使用 rand() 函数和双重交换法
通过两次随机交换来打乱数组。虽然时间复杂度为 O(n)
,但相较于 Fisher-Yates 算法来说不太常用。
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
void shuffle(int arr[], int n) {
for (int i = 0; i < n; i++) {
int j = rand() % n; // 随机生成索引
// 交换 arr[i] 和 arr[j]
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
// 再次随机交换
int k = rand() % n;
temp = arr[i];
arr[i] = arr[k];
arr[k] = temp;
}
}
int main() {
srand(time(0)); // 设置随机种子
int arr[] = {1, 2, 3, 4, 5};
int n = sizeof(arr) / sizeof(arr[0]);
shuffle(arr, n);
for (int i = 0; i < n; i++) {
printf("%d ", arr[i]);
}
printf("\n");
return 0;
}