#include "c_AmericanFlag.h" #include "c_Test.h" #include #include static int afs_string_extractor(const void* elem, c_size_t d, void* args) { (void)args; const char* str = *(const char* const*)elem; // 二级指针穿透锁字符 c_size_t len = strlen(str); if (d >= len) return -1; // 变长截止符 return (int)((unsigned char)str[d]); } TEST_CASE(test_c_AmericanFlagSort_大容量就地环置换压测) { // 构造一个包含 18 个元素、大量前缀交织("shor", "shore", "short", "sh")的变长恶劣方阵 const char* arr[] = { "she", "sells", "seashells", "by", "the", "sea", "shore", "the", "shells", "she", "sea", "shore", "sit", "short", "shor", "a", "sh", "z" }; c_size_t num = sizeof(arr) / sizeof(arr[0]); // 调用纯就地 MSD 排序,零动态辅助缓冲分配 c_err_t err = c_AmericanFlag_Sort(arr, num, sizeof(char*), afs_string_extractor, NULL); ASSERT_INT_EQ(C_ERR_OK, err); // 验证严格的全局字典序单调非减 for (c_size_t i = 0; i < num - 1; i++) { if (strcmp(arr[i], arr[i + 1]) > 0) { printf(" " COLOR_RED "[FAIL] 就地置换错位捕获: arr[%d]='%s' 排在 arr[%d]='%s' 的前面!" COLOR_RESET "\n", (int)i, arr[i], (int)(i + 1), arr[i + 1]); ASSERT_TRUE(false); return; } } // 校验极短终止符和极长串的拓扑归位状态 ASSERT_TRUE(strcmp("a", arr[0]) == 0); ASSERT_TRUE(strcmp("by", arr[1]) == 0); ASSERT_TRUE(strcmp("sea", arr[2]) == 0); // 极短终止符前缀必须完美垫底最前端 ASSERT_TRUE(strcmp("shells", arr[9]) == 0); // 极短终止符前缀必须完美垫底最前端 ASSERT_TRUE(strcmp("shor", arr[10]) == 0); ASSERT_TRUE(strcmp("shore", arr[11]) == 0); ASSERT_TRUE(strcmp("z", arr[num - 1]) == 0); // 尾部大收拢正确 } TEST_CASE(test_c_AmericanFlagSort_小样本Cutoff插入专线压测) { // 🌟 故意精简至 10 个数据(小于阈值 15),且打乱顺序、包含相同前缀和变长终止符 const char* arr_short[] = { "shore", "she", "sells", "sea", "sh", "shor", "sit", "short", "a", "sea" }; c_size_t num = sizeof(arr_short) / sizeof(arr_short[0]); // 调用入口:在第 0 字节探测时就因为总数 10 < 15 爆发降级,直接由 c_IP_MSD_InsertionSort 接管 c_err_t err = c_AmericanFlag_Sort(arr_short, num, sizeof(char*), afs_string_extractor, NULL); ASSERT_INT_EQ(C_ERR_OK, err); // 验证降级插入排序后的全局字典序是否完全单调非减 for (c_size_t i = 0; i < num - 1; i++) { if (strcmp(arr_short[i], arr_short[i + 1]) > 0) { printf(" " COLOR_RED "[FAIL] 降级插入排序错位: arr_short[%d]='%s' 居然排在 arr_short[%d]='%s' 前面!" COLOR_RESET "\n", (int)i, arr_short[i], (int)(i + 1), arr_short[i + 1]); ASSERT_TRUE(false); return; } } // 验证级联插入排序对短前缀终止符与后缀字典序的排序正确性 ASSERT_TRUE(strcmp("a", arr_short[0]) == 0); ASSERT_TRUE(strcmp("sea", arr_short[1]) == 0); ASSERT_TRUE(strcmp("sea", arr_short[2]) == 0); // 稳定排序项紧凑排布 ASSERT_TRUE(strcmp("sh", arr_short[4]) == 0); // 短前缀完美垫底 ASSERT_TRUE(strcmp("shor", arr_short[6]) == 0); ASSERT_TRUE(strcmp("shore", arr_short[7]) == 0); ASSERT_TRUE(strcmp("short", arr_short[8]) == 0); ASSERT_TRUE(strcmp("sit", arr_short[num-1]) == 0); } TEST_CASE(test_c_AmericanFlagSort_NonRec_大容量显式置换) { // 构造一个包含 18 个元素、大量前缀交织("shor", "shore", "short", "sh")的变长恶劣方阵 const char* arr[] = { "she", "sells", "seashells", "by", "the", "sea", "shore", "the", "shells", "she", "sea", "shore", "sit", "short", "shor", "a", "sh", "z" }; c_size_t num = sizeof(arr) / sizeof(arr[0]); // 调用纯就地 MSD 排序,零动态辅助缓冲分配 c_err_t err = c_AmericanFlag_NonRecSort(arr, num, sizeof(char*), afs_string_extractor, NULL, 0); ASSERT_INT_EQ(C_ERR_OK, err); // 验证严格的全局字典序单调非减 for (c_size_t i = 0; i < num - 1; i++) { if (strcmp(arr[i], arr[i + 1]) > 0) { printf(" " COLOR_RED "[FAIL] 就地置换错位捕获: arr[%d]='%s' 排在 arr[%d]='%s' 的前面!" COLOR_RESET "\n", (int)i, arr[i], (int)(i + 1), arr[i + 1]); ASSERT_TRUE(false); return; } } // 校验极短终止符和极长串的拓扑归位状态 ASSERT_TRUE(strcmp("a", arr[0]) == 0); ASSERT_TRUE(strcmp("by", arr[1]) == 0); ASSERT_TRUE(strcmp("sea", arr[2]) == 0); // 极短终止符前缀必须完美垫底最前端 ASSERT_TRUE(strcmp("shells", arr[9]) == 0); // 极短终止符前缀必须完美垫底最前端 ASSERT_TRUE(strcmp("shor", arr[10]) == 0); ASSERT_TRUE(strcmp("shore", arr[11]) == 0); ASSERT_TRUE(strcmp("z", arr[num - 1]) == 0); // 尾部大收拢正确 } TEST_CASE(test_c_AmericanFlagSort_NonRec_小样本插入排序) { // 🌟 故意精简至 10 个数据(小于阈值 15),且打乱顺序、包含相同前缀和变长终止符 const char* arr_short[] = { "shore", "she", "sells", "sea", "sh", "shor", "sit", "short", "a", "sea" }; c_size_t num = sizeof(arr_short) / sizeof(arr_short[0]); // 调用入口:在第 0 字节探测时就因为总数 10 < 15 爆发降级,直接由 c_IP_MSD_InsertionSort 接管 c_err_t err = c_AmericanFlag_NonRecSort(arr_short, num, sizeof(char*), afs_string_extractor, NULL, 0); ASSERT_INT_EQ(C_ERR_OK, err); // 验证降级插入排序后的全局字典序是否完全单调非减 for (c_size_t i = 0; i < num - 1; i++) { if (strcmp(arr_short[i], arr_short[i + 1]) > 0) { printf(" " COLOR_RED "[FAIL] 降级插入排序错位: arr_short[%d]='%s' 居然排在 arr_short[%d]='%s' 前面!" COLOR_RESET "\n", (int)i, arr_short[i], (int)(i + 1), arr_short[i + 1]); ASSERT_TRUE(false); return; } } // 验证级联插入排序对短前缀终止符与后缀字典序的排序正确性 ASSERT_TRUE(strcmp("a", arr_short[0]) == 0); ASSERT_TRUE(strcmp("sea", arr_short[1]) == 0); ASSERT_TRUE(strcmp("sea", arr_short[2]) == 0); // 稳定排序项紧凑排布 ASSERT_TRUE(strcmp("sh", arr_short[4]) == 0); // 短前缀完美垫底 ASSERT_TRUE(strcmp("shor", arr_short[6]) == 0); ASSERT_TRUE(strcmp("shore", arr_short[7]) == 0); ASSERT_TRUE(strcmp("short", arr_short[8]) == 0); ASSERT_TRUE(strcmp("sit", arr_short[num-1]) == 0); } // ========================================== // 5. 主集成入口 // ========================================== int main(void) { TEST_START(C_AmericanFlagSort_ZeroAux_TestSuite); RUN_TEST(test_c_AmericanFlagSort_大容量就地环置换压测); RUN_TEST(test_c_AmericanFlagSort_小样本Cutoff插入专线压测); RUN_TEST(test_c_AmericanFlagSort_NonRec_大容量显式置换); RUN_TEST(test_c_AmericanFlagSort_NonRec_小样本插入排序); TEST_REPORT(); return (g_test_registry.failed_count > 0 ? 1 : 0); }