You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C语言开发中如何缩减rand()随机数池实现不重复随机取值

无重复随机分配座位的实现方案

你目前使用的「抽到已分配座位就重试」是最易实现的方案,但在座位占用率较高时会产生大量无效随机数生成,性能波动大。除该方案外,有两种成熟的稳定实现方案:

方案1:Fisher-Yates 洗牌法

这是无重复随机抽样场景的通用最优方案,核心逻辑是提前把所有可用座位打乱顺序,分配时直接按顺序取用,全程不会出现重复值,也不需要重试判断。
实现步骤:

  • 将所有可用座位(对应你场景下前amount_rows/2排、每排amount_cols列的所有位置)映射为连续数组元素,每个元素存储座位的排、列号
  • 从数组末尾向前遍历,每次生成一个[0, 当前遍历下标]范围内的随机数,将当前遍历位置的元素和随机下标位置的元素交换,完成全数组随机打乱
  • 分配乘客座位时,按顺序从打乱后的数组中取出座位坐标赋值即可,所有取出的座位天然不重复

参考实现代码:

#include <stdlib.h>

typedef struct {
    int row;
    int col;
} Seat;

void assign_seats(int amount_rows, int amount_cols, Passenger passengers[amount_rows][amount_cols], int passenger_num) {
    int available_rows = amount_rows / 2;
    int total_available = available_rows * amount_cols;
    // 初始化可用座位池
    Seat* seat_pool = malloc(total_available * sizeof(Seat));
    int pool_idx = 0;
    for (int r = 0; r < available_rows; r++) {
        for (int c = 0; c < amount_cols; c++) {
            seat_pool[pool_idx].row = r;
            seat_pool[pool_idx].col = c;
            pool_idx++;
        }
    }

    // 执行Fisher-Yates洗牌
    for (int i = total_available - 1; i > 0; i--) {
        int rand_idx = rand() % (i + 1);
        Seat temp = seat_pool[i];
        seat_pool[i] = seat_pool[rand_idx];
        seat_pool[rand_idx] = temp;
    }

    // 直接按顺序分配,无重复
    for (int i = 0; i < passenger_num && i < total_available; i++) {
        int r = seat_pool[i].row;
        int c = seat_pool[i].col;
        passengers[r][c].in_row = 1;
    }

    free(seat_pool);
}

注意:你原有代码中rand() % amount_rows/2存在运算优先级问题,%和/优先级相同、按从左到右计算,实际执行逻辑是(rand() % amount_rows)/2,如果要实现对amount_rows/2取模,需要给除数加括号写成rand() % (amount_rows/2)。

方案2:动态剩余池抽样

这个方案不需要提前完成全量洗牌,适合不需要一次性分配完所有座位的场景:

  • 同样先初始化存储所有可用座位的数组,维护一个变量记录当前剩余可用座位数,初始值为总可用座位数
  • 每次需要分配座位时,生成[0, 当前剩余座位数-1]范围的随机下标,取出该下标的座位用于分配
  • 将数组末尾的可用座位移动到刚才取出座位的下标位置,剩余可用座位数减1
  • 重复上述过程直到完成所有分配,同样不会产生重复抽取,也没有无效重试

方案对比

  • 重试法:代码量最少,不需要额外内存,但座位占用率超过70%后无效重试次数会快速上升,仅适合总座位数极少的场景
  • 洗牌法:性能稳定,一次打乱后分配座位时间复杂度为O(1),适合需要批量分配所有座位的模拟场景
  • 动态剩余池:内存占用和洗牌法一致,支持动态按需分配,不需要提前完成全量打乱,灵活性更高

内容的提问来源于stack exchange,提问作者Harry Duffy

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.30 07:15:40