Files
cKit/Foundation/c_KnuthShuffle.c
T
2026-08-30 22:24:45 +08:00

52 lines
1.6 KiB
C

#include <c_KnuthShuffle.h>
#include "c_Random.h"
void c_KnuthShuffle(void* base, c_size_t num, c_size_t size) {
// 边界与防御性校验:元素少于2个或大小非法时无需洗牌
if (!base || num < 2 || size == 0) {
return;
}
c_Random_Init();
char* array_base = (char*)base;
// 采用局部栈分配缓冲区,避免堆内存分配开销,提升交换效率
// 256字节足够容纳绝大多数基础类型与常见的结构体
char temp_buf[256];
// 从后往前进行滑窗交换
for (c_size_t i = num; i > 1; i--) {
c_size_t current_idx = i-1;
// 安全地在 [0, i] 闭区间内抽取一个随机目标下标
// 依托您之前的去偏差 c_Random_RangeU64 确保概率绝对均等
c_size_t j = (c_size_t)c_Random_RangeU64(0, current_idx);
// 如果抽中自身,则无需原地交换
if (current_idx == j) {
continue;
}
// 计算需要交换的两个元素在内存中的绝对地址
char* elem_i = array_base + (current_idx * size);
char* elem_j = array_base + (j * size);
// 泛型就地内存交换 (In-place Swap)
c_size_t bytes_to_swap = size;
while (bytes_to_swap > 0) {
c_size_t chunk = (bytes_to_swap < sizeof(temp_buf)) ? bytes_to_swap : sizeof(temp_buf);
memcpy(temp_buf, elem_i, chunk);
memcpy(elem_i, elem_j, chunk);
memcpy(elem_j, temp_buf, chunk);
elem_i += chunk;
elem_j += chunk;
bytes_to_swap -= chunk;
}
}
}