Search/Sort

This commit is contained in:
2026-08-29 01:58:00 +08:00
parent 8e95904cc4
commit a0758766c5
56 changed files with 5425 additions and 0 deletions
+79
View File
@@ -0,0 +1,79 @@
#ifndef INCLUDED_C_BINARYINSERTIONSORT_H
#define INCLUDED_C_BINARYINSERTIONSORT_H
#ifndef INCLUDED_C_TYPES_H
#include <c_Types.h>
#endif /*INCLUDED_C_TYPES_H*/
#ifndef INCLUDED_C_MEMORY_H
#include <c_Memory.h>
#endif /*INCLUDED_C_MEMORY_H*/
/* ------------------------------------------------------------------------------------------------------------------ */
/* */
/**
* 通用折半插入排序函数
* @param base 指向待排序数组首元素的指针
* @param num 数组中元素的个数
* @param size 每个元素的大小(字节数)
* @param compar 指向比较函数的指针
*/
C_STATIC_FORCE_INLINE
void c_BinaryInsertionSort(void* base, c_size_t num, c_size_t size,
int (*compar)(const void*, const void*)) {
char* arr = (char*)base; // 强转为 char* 以便按单字节进行指针偏移
// 分配一块临时内存,用于存放当前要插入的“哨兵”元素(temp)
#define STACK_LIMIT 128
char stack_buf[STACK_LIMIT];
void* temp = NULL;
if (size <= STACK_LIMIT) {
temp = stack_buf;
} else {
temp = C_ALLOC(size);
if (temp == NULL) return;
}
for (c_size_t i = 1; i < num; i++) {
// temp = arr[i]:备份当前要插入的元素
memcpy(temp, arr + (i * size), size);
// 1. 使用二分查找决定插入位置 [left, right]
long long left = 0;
long long right = i - 1;
while (left <= right) {
long long mid = left + (right - left) / 2;
// 为了保证排序的稳定性(Stability),
// 当 mid 元素等于 temp 时,应当继续向右区间查找,把 temp 放到相同元素的后面
if (compar(arr + (mid * size), temp) <= 0) {
left = mid + 1; // 目标位置在右边
} else {
right = mid - 1; // 目标位置在左边
}
}
// 循环结束时,left 就是元素应该插入的目标索引位置
// 2. 将 [left, i-1] 区间的元素全部向后移动一个位置
for (long long j = i - 1; j >= left; j--) {
memcpy(arr + ((j + 1) * size), arr + (j * size), size);
}
// 3. 将 temp 插入到腾出来的 left 位置
memcpy(arr + (left * size), temp, size);
}
// Only trigger free if it was actually allocated from the heap
if (size > STACK_LIMIT) {
C_FREE(temp);
}
#undef STACK_LIMIT
}
#endif /*INCLUDED_C_BINARYINSERTIONSORT_H*/