Files
cKit/Foundation/c_RBTree.t.c
T

123 lines
5.4 KiB
C
Raw Normal View History

2026-08-30 02:51:25 +08:00
#include "c_RBTree.h"
#include <stdlib.h>
#include <stdio.h>
#include "c_Test.h"
// 专属的具体类型整型比较算子回调实现
static int int_compare_operator(const void* a, const void* b) {
return *(const int*)a - *(const int*)b;
}
// 辅助函数:通过递归计算树的黑高(Black Height)并验证红黑树的关键平衡性质
static int verify_rb_properties(const c_RBNode_t* node, int* error_flag) {
if (node == NULL) {
return 1; // 空节点(叶子)默认为黑色,黑高贡献为 1
}
// 性质 4 校验:如果一个节点是红色的,则它的两个子节点必须是黑色的(红红不能相连)
if (c_RBTree_GetColor(node) == C_RB_RED) {
if (c_RBTree_GetColor(node->left) == C_RB_RED || c_RBTree_GetColor(node->right) == C_RB_RED) {
*error_flag = 1; // 违反红黑树性质
}
}
// 递归计算左右子树的黑高
int left_black_height = verify_rb_properties(node->left, error_flag);
int right_black_height = verify_rb_properties(node->right, error_flag);
// 性质 5 校验:从任一节点到其每个叶子的所有简单路径都包含相同数目的黑色节点(黑高必须绝对相等)
if (left_black_height != right_black_height) {
*error_flag = 2; // 违反黑高平衡性质
}
// 返回当前节点的总黑高
return left_black_height + (c_RBTree_GetColor(node) == C_RB_BLACK ? 1 : 0);
}
// ==================================================================================================================
// 核心测试用例
// ==================================================================================================================
#define ASSERT_FALSE(condition) \
ASSERT_TRUE(!condition)
TEST_CASE(test_naked_rb_tree_ultimate_closure) {
c_RBTree_t tree;
// 1. 初始化验证:必须满足极致零堆开销契约
ASSERT_INT_EQ(C_ERR_OK, c_RBTree_Init(&tree, sizeof(int), int_compare_operator, NULL));
ASSERT_INT_EQ(0, (int)c_RBTree_Size(&tree));
ASSERT_TRUE(tree.root == NULL); // 空树状态下,根指针变量的值严格为 0 (NULL)
// 2. 【高密度顺序与交叉插入】:强迫其内部连续触发无哨兵旋转、亲代重组与颜色翻转
// 故意采用会引发严重倾斜的序列,测试自平衡状态机的抗压极限
int dataset[] = {40, 20, 60, 10, 30, 50, 70, 5, 15, 25, 35};
for (int i = 0; i < 11; i++) {
ASSERT_INT_EQ(C_ERR_OK, c_RBTree_Insert(&tree, &dataset[i]));
}
// 实时读取 Size 契约验证
ASSERT_INT_EQ(11, (int)c_RBTree_Size(&tree));
// 3. 验证查重机制与包含性检测 (Contains)
int duplicate = 30;
int fake_key = 999;
ASSERT_INT_EQ(C_ERR_PARAM, c_RBTree_Insert(&tree, &duplicate)); // 重复键必须被去重拦截墙强力回绝
ASSERT_TRUE(c_RBTree_Contains(&tree, &duplicate));
ASSERT_FALSE(c_RBTree_Contains(&tree, &fake_key));
// 4. 数学及拓扑性质动态审计
int balance_error_flag = 0;
verify_rb_properties(tree.root, &balance_error_flag);
ASSERT_INT_EQ_MSG(0, balance_error_flag, "Red-Black Tree invariant properties violated after insertions!");
ASSERT_INT_EQ(C_RB_BLACK, c_RBTree_GetColor(tree.root)); // 性质 2:根节点必须保持绝对黑色
// 5. 【无哨兵极限删除考验】:连续定点抹杀节点资源,触发所有最复杂的黑高调整分支
int kill_leaf = 35; // 分支 A: 移除一个普通的叶子项
int kill_single_child = 5; // 分支 B: 移除一个带单子女的节点
int kill_double_child = 20; // 分支 C: 终极考验,移除一个同时带有左右复杂子树的核心对称交叉点
// 定点抹杀第一击
ASSERT_INT_EQ(C_ERR_OK, c_RBTree_Remove(&tree, &kill_leaf));
ASSERT_INT_EQ(10, (int)c_RBTree_Size(&tree));
ASSERT_FALSE(c_RBTree_Contains(&tree, &kill_leaf));
// 定点抹杀第二击
ASSERT_INT_EQ(C_ERR_OK, c_RBTree_Remove(&tree, &kill_single_child));
ASSERT_INT_EQ(9, (int)c_RBTree_Size(&tree));
ASSERT_FALSE(c_RBTree_Contains(&tree, &kill_single_child));
// 定点抹杀第三击(双子树迁移)
ASSERT_INT_EQ(C_ERR_OK, c_RBTree_Remove(&tree, &kill_double_child));
ASSERT_INT_EQ(8, (int)c_RBTree_Size(&tree));
ASSERT_FALSE(c_RBTree_Contains(&tree, &kill_double_child));
// 6. 删除后的黑高平衡性二次严苛审计
balance_error_flag = 0;
verify_rb_properties(tree.root, &balance_error_flag);
ASSERT_INT_EQ_MSG(0, balance_error_flag, "Red-Black Tree broke its black-height balance after dynamic removals!");
ASSERT_INT_EQ(C_RB_BLACK, c_RBTree_GetColor(tree.root)); // 根节点依然稳健为黑
// 7. 验证快速清空机制与纯净还原 (Clear)
c_RBTree_Clear(&tree);
ASSERT_INT_EQ(0, (int)c_RBTree_Size(&tree));
ASSERT_TRUE(tree.root == NULL); // 必须在物理堆中 0 滞留,控制头完美复位到 0 态
c_RBTree_Destroy(&tree);
}
// ==================================================================================================================
// 主测试入口
// ==================================================================================================================
int main(void) {
printf("\n");
TEST_START(C_Naked_RedBlackTree_Integrated_Tests);
// 运行无哨兵加固后的红黑树核心功能及自修复流验证
RUN_TEST(test_naked_rb_tree_ultimate_closure);
TEST_REPORT();
RETURN_TEST_STATUS;
}