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;
}