Search / Sort
This commit is contained in:
@@ -0,0 +1,51 @@
|
||||
#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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user