112 lines
3.7 KiB
C
112 lines
3.7 KiB
C
#include "c_ShellSort.h"
|
|||
|
|
#include <stdlib.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
#include "c_Test.h"
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 1. 测试用例伴生:比对器与业务结构体定义
|
||
|
|
// ==========================================
|
||
|
|
static int sort_compare_ints_with_args(const void* a, const void* b, void* args) {
|
||
|
|
(void)args;
|
||
|
|
int arg1 = *(const int*)a;
|
||
|
|
int arg2 = *(const int*)b;
|
||
|
|
if (arg1 < arg2) return -1;
|
||
|
|
if (arg1 > arg2) return 1;
|
||
|
|
return 0;
|
||
|
|
}
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
char name; // 任务标识符(字符型)
|
||
|
|
int age; // 任务时间周期
|
||
|
|
int priority; // 任务优先级
|
||
|
|
} Task_t;
|
||
|
|
|
||
|
|
// 复合结构体多级比对器:优先比较优先级(降序),优先级相同时按年龄(升序)
|
||
|
|
static int sort_compare_tasks(const void* a, const void* b, void* args) {
|
||
|
|
(void)args;
|
||
|
|
const Task_t* t1 = (const Task_t*)a;
|
||
|
|
const Task_t* t2 = (const Task_t*)b;
|
||
|
|
|
||
|
|
if (t1->priority != t2->priority) {
|
||
|
|
return t2->priority - t1->priority;
|
||
|
|
}
|
||
|
|
return t1->age - t2->age;
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 2. 自动化测试用例集
|
||
|
|
// ==========================================
|
||
|
|
TEST_CASE(test_c_ShellSort_IntArray) {
|
||
|
|
// 大跨度无序、包含相同元素的经典整型测试集
|
||
|
|
int arr[] = { 81, 94, 11, 96, 12, 35, 17, 95, 28, 58, 41, 75, 15 };
|
||
|
|
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||
|
|
|
||
|
|
c_ShellSort(arr, num, sizeof(int), sort_compare_ints_with_args, NULL);
|
||
|
|
|
||
|
|
// 验证区间整体是否呈现绝对升序状态
|
||
|
|
for (c_size_t i = 0; i < num - 1; i++) {
|
||
|
|
ASSERT_TRUE(arr[i] <= arr[i + 1]);
|
||
|
|
}
|
||
|
|
ASSERT_INT_EQ(11, arr[0]); // 检查全局最小值
|
||
|
|
ASSERT_INT_EQ(96, arr[num - 1]); // 检查全局最大值
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_CASE(test_c_ShellSort_StructArray) {
|
||
|
|
// 结构体多关键字字段级搬运重排测试
|
||
|
|
Task_t tasks[] = {
|
||
|
|
{ 'A', 30, 2 },
|
||
|
|
{ 'B', 25, 5 },
|
||
|
|
{ 'C', 45, 2 },
|
||
|
|
{ 'D', 18, 5 }
|
||
|
|
};
|
||
|
|
c_size_t num = sizeof(tasks) / sizeof(tasks[0]);
|
||
|
|
|
||
|
|
c_ShellSort(tasks, num, sizeof(Task_t), sort_compare_tasks, NULL);
|
||
|
|
|
||
|
|
// 预期重排顺序:tasks[0] 应为 'D'(5级/18岁) -> tasks[1] 应为 'B'(5级/25岁) -> tasks[2] 应为 'A'(2级/30岁)
|
||
|
|
ASSERT_INT_EQ(5, tasks[0].priority);
|
||
|
|
ASSERT_INT_EQ(18, tasks[0].age);
|
||
|
|
ASSERT_INT_EQ('D', tasks[0].name);
|
||
|
|
|
||
|
|
ASSERT_INT_EQ(5, tasks[1].priority);
|
||
|
|
ASSERT_INT_EQ(25, tasks[1].age);
|
||
|
|
ASSERT_INT_EQ('B', tasks[1].name);
|
||
|
|
|
||
|
|
ASSERT_INT_EQ(2, tasks[2].priority);
|
||
|
|
ASSERT_INT_EQ(30, tasks[2].age);
|
||
|
|
ASSERT_INT_EQ('A', tasks[2].name);
|
||
|
|
}
|
||
|
|
|
||
|
|
TEST_CASE(test_c_ShellSort_Security_And_Edges) {
|
||
|
|
// 强行推入完全逆序的极值数组,压测 `j -= gap` 的前置边界拦截逻辑
|
||
|
|
int rev_arr[] = { 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||
|
|
c_size_t num = sizeof(rev_arr) / sizeof(rev_arr[0]);
|
||
|
|
|
||
|
|
c_ShellSort(rev_arr, num, sizeof(int), sort_compare_ints_with_args, NULL);
|
||
|
|
for (c_size_t i = 0; i < num - 1; i++) {
|
||
|
|
ASSERT_TRUE(rev_arr[i] < rev_arr[i + 1]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 极端输入安全防御测试(验证单元素或非法参数下能安全防回绕并优雅退出)
|
||
|
|
int single_arr[] = { 777 };
|
||
|
|
c_ShellSort(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||
|
|
c_ShellSort(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||
|
|
ASSERT_INT_EQ(777, single_arr[0]);
|
||
|
|
}
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 3. 独立测试运行入口
|
||
|
|
// ==========================================
|
||
|
|
int main(void) {
|
||
|
|
TEST_START(C_ShellSort_Isolated_TestSuite);
|
||
|
|
|
||
|
|
// 顺序调度并运行专项测试集
|
||
|
|
RUN_TEST(test_c_ShellSort_IntArray);
|
||
|
|
RUN_TEST(test_c_ShellSort_StructArray);
|
||
|
|
RUN_TEST(test_c_ShellSort_Security_And_Edges);
|
||
|
|
|
||
|
|
TEST_REPORT();
|
||
|
|
|
||
|
|
RETURN_TEST_STATUS;
|
||
|
|
}
|