Search / Sort
This commit is contained in:
@@ -0,0 +1,381 @@
|
||||
#include "c_QuickSort.h"
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include "c_Test.h"
|
||||
|
||||
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 id;
|
||||
int rank;
|
||||
} UserNode_t;
|
||||
|
||||
static int sort_compare_users(const void* a, const void* b, void* args) {
|
||||
(void)args;
|
||||
const UserNode_t* u1 = (const UserNode_t*)a;
|
||||
const UserNode_t* u2 = (const UserNode_t*)b;
|
||||
return u1->rank - u2->rank; // 简单按 rank 升序比对
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 4. 自动化测试用例集
|
||||
// ==========================================
|
||||
TEST_CASE(test_c_QuickSort_Recursive_IntArray) {
|
||||
int arr[] = { 24, 9, 85, 32, 75, 5, 66 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_Recursive(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(5, arr[0]);
|
||||
ASSERT_INT_EQ(85, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_Recursive_StructArray) {
|
||||
UserNode_t users[] = {
|
||||
{ 'M', 90 },
|
||||
{ 'N', 10 },
|
||||
{ 'O', 45 }
|
||||
};
|
||||
c_size_t num = sizeof(users) / sizeof(users[0]);
|
||||
|
||||
c_QuickSort_Recursive(users, num, sizeof(UserNode_t), sort_compare_users, NULL);
|
||||
|
||||
// 预期重排顺序: N(10) -> O(45) -> M(90)
|
||||
ASSERT_INT_EQ(10, users[0].rank);
|
||||
ASSERT_TRUE(users[0].id == 'N');
|
||||
|
||||
ASSERT_INT_EQ(45, users[1].rank);
|
||||
ASSERT_TRUE(users[1].id == 'O');
|
||||
|
||||
ASSERT_INT_EQ(90, users[2].rank);
|
||||
ASSERT_TRUE(users[2].id == 'M');
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_Recursive_Edges) {
|
||||
// 压测完全倒序的极值输入,检查安全拦截
|
||||
int rev_arr[] = { 4, 3, 2, 1 };
|
||||
c_size_t num = sizeof(rev_arr) / sizeof(rev_arr[0]);
|
||||
|
||||
c_QuickSort_Recursive(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[] = { 567 };
|
||||
c_QuickSort_Recursive(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
c_QuickSort_Recursive(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
ASSERT_INT_EQ(567, single_arr[0]);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
typedef struct {
|
||||
char label;
|
||||
int major;
|
||||
int minor;
|
||||
} NodeItem_t;
|
||||
|
||||
// 复合多级比对器:优先按 major 升序,相同时按 minor 降序
|
||||
static int sort_compare_nodes(const void* a, const void* b, void* args) {
|
||||
(void)args;
|
||||
const NodeItem_t* n1 = (const NodeItem_t*)a;
|
||||
const NodeItem_t* n2 = (const NodeItem_t*)b;
|
||||
if (n1->major != n2->major) {
|
||||
return n1->major - n2->major;
|
||||
}
|
||||
return n2->minor - n1->minor;
|
||||
}
|
||||
|
||||
// ==========================================
|
||||
// 4. 自动化测试用例集
|
||||
// ==========================================
|
||||
TEST_CASE(test_c_QuickSort_3Way_MassiveDuplicates) {
|
||||
int arr[] = { 9, 3, 9, 9, 7, 3, 9, 1, 9, 7, 9, 9, 3, 9 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_3Way(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(1, arr[0]);
|
||||
ASSERT_INT_EQ(3, arr[1]);
|
||||
ASSERT_INT_EQ(3, arr[2]);
|
||||
ASSERT_INT_EQ(9, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_3Way_StructArray) {
|
||||
// 2. 复杂多关键字结构体数组精确下标引用校验
|
||||
NodeItem_t nodes[] = {
|
||||
{ 'A', 500, 20 },
|
||||
{ 'B', 300, 60 },
|
||||
{ 'C', 500, 80 }, // major 同为 500,但 minor 80 应该排在 20 的前面
|
||||
{ 'D', 400, 40 }
|
||||
};
|
||||
c_size_t num = sizeof(nodes) / sizeof(nodes[0]);
|
||||
|
||||
c_QuickSort_3Way(nodes, num, sizeof(NodeItem_t), sort_compare_nodes, NULL);
|
||||
|
||||
// 预期重排顺序: B(300/60) -> D(400/40) -> C(500/80) -> A(500/20)
|
||||
ASSERT_INT_EQ(300, nodes[0].major);
|
||||
ASSERT_TRUE(nodes[0].label == 'B');
|
||||
|
||||
ASSERT_INT_EQ(400, nodes[1].major);
|
||||
ASSERT_TRUE(nodes[1].label == 'D');
|
||||
|
||||
ASSERT_INT_EQ(500, nodes[2].major);
|
||||
ASSERT_INT_EQ(80, nodes[2].minor); // 降序次键优先被推出
|
||||
ASSERT_TRUE(nodes[2].label == 'C');
|
||||
|
||||
ASSERT_INT_EQ(500, nodes[3].major);
|
||||
ASSERT_INT_EQ(20, nodes[3].minor);
|
||||
ASSERT_TRUE(nodes[3].label == 'A');
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_3Way_EdgesAndReverse) {
|
||||
// 3. 完全逆序极值序列压测
|
||||
int rev_arr[] = { 5, 4, 3, 2, 1 };
|
||||
c_size_t num = sizeof(rev_arr) / sizeof(rev_arr[0]);
|
||||
|
||||
c_QuickSort_3Way(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]);
|
||||
}
|
||||
|
||||
// 4. 单元素与非法空边界拦截
|
||||
int single_arr[] = { 9999 };
|
||||
c_QuickSort_3Way(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
c_QuickSort_3Way(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
ASSERT_INT_EQ(9999, single_arr[0]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_2Way_MassiveAndCutoff) {
|
||||
// 1. 构建一个长距离乱序、超过截断阈值(> 15)的恶劣元素阵列
|
||||
int arr[] = { 99, 4, 23, 87, 12, 56, 34, 11, 90, 8, 45, 68, 22, 1, 75, 43, 19, 105, 0, 55 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_2Way_Optimized(arr, num, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
|
||||
// 验证严格单调性
|
||||
for (c_size_t i = 0; i < num - 1; i++) {
|
||||
if (arr[i] > arr[i + 1]) {
|
||||
// 如果发生局部乱序,精准抛出报错位置和具体数据对对碰
|
||||
ASSERT_INT_EQ(arr[i + 1], arr[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT_INT_EQ(0, arr[0]);
|
||||
ASSERT_INT_EQ(1, arr[1]);
|
||||
ASSERT_INT_EQ(105, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_2Way_WorstCaseRegression) {
|
||||
// 2. 强推完全逆序的极值分布数组。
|
||||
// 在普通快排里这会瞬间引发 O(N²) 的最坏情况,但三数取中能直接在 $O(1)$ 时间内把枢轴拉回到最优的中位数位置
|
||||
int arr[] = { 20, 19, 18, 17, 16, 15, 14, 13, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_2Way_Optimized(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(1, arr[0]);
|
||||
ASSERT_INT_EQ(20, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_2Way_HeavyDuplicates) {
|
||||
// 3. 压测大量重复元素的恶劣数据分布(Dijkstra 3-way 测试中的那个顽固集合)
|
||||
int arr[] = { 9, 3, 9, 9, 7, 3, 9, 1, 9, 7, 9, 9, 3, 9 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_2Way_Optimized(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(1, arr[0]);
|
||||
ASSERT_INT_EQ(3, arr[1]);
|
||||
ASSERT_INT_EQ(7, arr[4]);
|
||||
ASSERT_INT_EQ(9, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_2Way_Edges) {
|
||||
int single_arr[] = { 7777 };
|
||||
c_QuickSort_2Way_Optimized(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
c_QuickSort_2Way_Optimized(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
ASSERT_INT_EQ(7777, single_arr[0]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_BM_MassiveDuplicates) {
|
||||
// 投入那个之前极易引发枢轴内存掉包和无符号数下溢的经典恶劣重复数据集合
|
||||
int arr[] = { 9, 3, 9, 9, 7, 3, 9, 1, 9, 7, 9, 9, 3, 9 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_BentleyMcIlroy(arr, num, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
|
||||
// 1. 验证单调非减
|
||||
for (c_size_t i = 0; i < num - 1; i++) {
|
||||
if (arr[i] > arr[i + 1]) {
|
||||
ASSERT_INT_EQ(arr[i + 1], arr[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// 2. 深度精确校验中央和两端的全部插槽值
|
||||
ASSERT_INT_EQ(1, arr[0]);
|
||||
ASSERT_INT_EQ(3, arr[1]);
|
||||
ASSERT_INT_EQ(3, arr[2]);
|
||||
ASSERT_INT_EQ(3, arr[3]);
|
||||
ASSERT_INT_EQ(7, arr[4]);
|
||||
ASSERT_INT_EQ(7, arr[5]);
|
||||
ASSERT_INT_EQ(9, arr[6]);
|
||||
ASSERT_INT_EQ(9, arr[7]);
|
||||
ASSERT_INT_EQ(9, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_BM_ComplexPermutation) {
|
||||
// 常规混合高度无序无重复梯度大样本压测,验证 Bentley-McIlroy 的广谱鲁棒性
|
||||
int arr[] = { 42, 12, 88, 5, 67, 1, 99, 34, 11, 73, 22, 15, 60 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_BentleyMcIlroy(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(1, arr[0]);
|
||||
ASSERT_INT_EQ(99, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_BM_Edges) {
|
||||
int single_arr[] = { 55555 };
|
||||
c_QuickSort_BentleyMcIlroy(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
c_QuickSort_BentleyMcIlroy(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
ASSERT_INT_EQ(55555, single_arr[0]);
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------------------------------------------------ */
|
||||
/* */
|
||||
|
||||
typedef struct {
|
||||
char token;
|
||||
int weight;
|
||||
} ElementNode_t;
|
||||
|
||||
static int sort_compare_elements(const void* a, const void* b, void* args) {
|
||||
(void)args;
|
||||
const ElementNode_t* e1 = (const ElementNode_t*)a;
|
||||
const ElementNode_t* e2 = (const ElementNode_t*)b;
|
||||
return e1->weight - e2->weight;
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_Iterative_BasicInts) {
|
||||
// 1. 标准乱序混合整型数组非递归迭代排序测试
|
||||
int arr[] = { 42, 17, 85, 3, 64, 12, 99, 32, 5, 55 };
|
||||
c_size_t num = sizeof(arr) / sizeof(arr[0]);
|
||||
|
||||
c_QuickSort_Iterative(arr, num, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
|
||||
for (c_size_t i = 0; i < num - 1; i++) {
|
||||
if (arr[i] > arr[i + 1]) {
|
||||
ASSERT_INT_EQ(arr[i + 1], arr[i]);
|
||||
return;
|
||||
}
|
||||
}
|
||||
ASSERT_INT_EQ(3, arr[0]);
|
||||
ASSERT_INT_EQ(5, arr[1]);
|
||||
ASSERT_INT_EQ(99, arr[num - 1]);
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_Iterative_StructArray) {
|
||||
// 2. 复杂自定义结构体对象在非递归模拟栈状态下的字段流转测试
|
||||
ElementNode_t nodes[] = {
|
||||
{ 'X', 800 },
|
||||
{ 'Y', 200 },
|
||||
{ 'Z', 500 },
|
||||
{ 'W', 100 }
|
||||
};
|
||||
c_size_t num = sizeof(nodes) / sizeof(nodes[0]);
|
||||
|
||||
c_QuickSort_Iterative(nodes, num, sizeof(ElementNode_t), sort_compare_elements, NULL);
|
||||
|
||||
// 预期升序排布顺序:W(100) -> Y(200) -> Z(500) -> X(800)
|
||||
ASSERT_INT_EQ(100, nodes[0].weight);
|
||||
ASSERT_TRUE(nodes[0].token == 'W');
|
||||
|
||||
ASSERT_INT_EQ(200, nodes[1].weight);
|
||||
ASSERT_TRUE(nodes[1].token == 'Y');
|
||||
|
||||
ASSERT_INT_EQ(500, nodes[2].weight);
|
||||
ASSERT_TRUE(nodes[2].token == 'Z');
|
||||
|
||||
ASSERT_INT_EQ(800, nodes[3].weight);
|
||||
ASSERT_TRUE(nodes[3].token == 'X');
|
||||
}
|
||||
|
||||
TEST_CASE(test_c_QuickSort_Iterative_ExtremeEdges) {
|
||||
// 3. 压测完全有序和完全逆序序列,高强度检验模拟栈的大小和入栈逻辑安全性
|
||||
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_QuickSort_Iterative(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]);
|
||||
}
|
||||
|
||||
// 4. 空参数以及单体超边界数组拦截防御
|
||||
int single_arr[] = { 88888 };
|
||||
c_QuickSort_Iterative(single_arr, 1, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
c_QuickSort_Iterative(NULL, 0, sizeof(int), sort_compare_ints_with_args, NULL);
|
||||
ASSERT_INT_EQ(88888, single_arr[0]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// ==========================================
|
||||
// 5. 独立测试运行入口
|
||||
// ==========================================
|
||||
int main(void) {
|
||||
TEST_START(C_SimpleQuickSort_Isolated_TestSuite);
|
||||
|
||||
// 顺序触发快速排序测试
|
||||
RUN_TEST(test_c_QuickSort_Recursive_IntArray);
|
||||
RUN_TEST(test_c_QuickSort_Recursive_StructArray);
|
||||
RUN_TEST(test_c_QuickSort_Recursive_Edges);
|
||||
|
||||
// 触发专项三路快排验证
|
||||
RUN_TEST(test_c_QuickSort_3Way_MassiveDuplicates);
|
||||
RUN_TEST(test_c_QuickSort_3Way_StructArray);
|
||||
RUN_TEST(test_c_QuickSort_3Way_EdgesAndReverse);
|
||||
|
||||
RUN_TEST(test_c_QuickSort_2Way_MassiveAndCutoff);
|
||||
RUN_TEST(test_c_QuickSort_2Way_WorstCaseRegression);
|
||||
RUN_TEST(test_c_QuickSort_2Way_HeavyDuplicates);
|
||||
RUN_TEST(test_c_QuickSort_2Way_Edges);
|
||||
|
||||
RUN_TEST(test_c_QuickSort_BM_MassiveDuplicates);
|
||||
RUN_TEST(test_c_QuickSort_BM_ComplexPermutation);
|
||||
RUN_TEST(test_c_QuickSort_BM_Edges);
|
||||
|
||||
RUN_TEST(test_c_QuickSort_Iterative_BasicInts);
|
||||
RUN_TEST(test_c_QuickSort_Iterative_StructArray);
|
||||
RUN_TEST(test_c_QuickSort_Iterative_ExtremeEdges);
|
||||
|
||||
TEST_REPORT();
|
||||
|
||||
RETURN_TEST_STATUS;
|
||||
}
|
||||
Reference in New Issue
Block a user