92 lines
2.9 KiB
C
92 lines
2.9 KiB
C
#include "c_RBTree.h"
|
|||
|
|
#include <stdlib.h>
|
||
|
|
#include <stdio.h>
|
||
|
|
|
||
|
|
|
||
|
|
typedef struct {
|
||
|
|
int id;
|
||
|
|
char name[32];
|
||
|
|
} Task_t;
|
||
|
|
|
||
|
|
// 比較回呼函數
|
||
|
|
int compare_tasks(const void* a, const void* b) {
|
||
|
|
return (((Task_t*)a)->id - ((Task_t*)b)->id);
|
||
|
|
}
|
||
|
|
|
||
|
|
// 走訪時驗證遞增順序
|
||
|
|
int g_last_id = -1;
|
||
|
|
void visit_verify(void* data, void* cl) {
|
||
|
|
Task_t* t = (Task_t*)data;
|
||
|
|
assert(t->id > g_last_id); // 必須嚴格遞增
|
||
|
|
g_last_id = t->id;
|
||
|
|
}
|
||
|
|
|
||
|
|
void test_log(const char* name) {
|
||
|
|
printf("[PASS] %s\n", name);
|
||
|
|
}
|
||
|
|
|
||
|
|
int main() {
|
||
|
|
printf("==================================================\n");
|
||
|
|
printf(" 開始執行 c_RBTree (含 O(log N) Remove) 最終整合測試\n");
|
||
|
|
printf("==================================================\n\n");
|
||
|
|
|
||
|
|
c_RBTree_t tree;
|
||
|
|
c_RBTree_Init(&tree, sizeof(Task_t), compare_tasks);
|
||
|
|
|
||
|
|
Task_t tasks[] = {
|
||
|
|
{40, "Task_40"}, {20, "Task_20"}, {60, "Task_60"},
|
||
|
|
{10, "Task_10"}, {30, "Task_30"}, {50, "Task_50"}, {70, "Task_70"}
|
||
|
|
};
|
||
|
|
|
||
|
|
// 1. 批次推入資料
|
||
|
|
for (int i = 0; i < 7; i++) {
|
||
|
|
c_RBTree_Insert(&tree, &tasks[i]);
|
||
|
|
}
|
||
|
|
assert(tree.size == 7);
|
||
|
|
test_log("1. 批次推入 7 筆資料成功");
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 2. 測試刪除葉子節點 (Task 10)
|
||
|
|
// ==========================================
|
||
|
|
Task_t target = {10, ""};
|
||
|
|
c_err_t err = c_RBTree_Remove(&tree, &target);
|
||
|
|
assert(err == C_ERR_SUCCESS);
|
||
|
|
assert(tree.size == 6);
|
||
|
|
assert(c_RBTree_Find(&tree, &target) == NULL); // 預期找不到
|
||
|
|
|
||
|
|
// 驗證刪除後的結構順序性
|
||
|
|
g_last_id = -1;
|
||
|
|
c_RBTree_InOrder(&tree, visit_verify, NULL);
|
||
|
|
test_log("2. 成功刪除葉子節點 (10) 且中序走訪維持平衡有序");
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 3. 測試刪除擁有多個子節點的核心根節點 (Task 40)
|
||
|
|
// ==========================================
|
||
|
|
target.id = 40;
|
||
|
|
err = c_RBTree_Remove(&tree, &target);
|
||
|
|
assert(err == C_ERR_SUCCESS);
|
||
|
|
assert(tree.size == 5);
|
||
|
|
assert(c_RBTree_Find(&tree, &target) == NULL);
|
||
|
|
|
||
|
|
// 再次驗證刪除後的結構順序性
|
||
|
|
g_last_id = -1;
|
||
|
|
c_RBTree_InOrder(&tree, visit_verify, NULL);
|
||
|
|
test_log("3. 成功刪除雙子核心節點 (40) 且平衡移植狀態正確");
|
||
|
|
|
||
|
|
// ==========================================
|
||
|
|
// 4. 刪除不存在的鍵值與無效參數防呆
|
||
|
|
// ==========================================
|
||
|
|
target.id = 999;
|
||
|
|
assert(c_RBTree_Remove(&tree, &target) == C_ERR_NOT_FOUND);
|
||
|
|
assert(c_RBTree_Remove(NULL, &target) == C_ERR_PARAM);
|
||
|
|
test_log("4. 刪除越界與無效引數防呆驗證成功");
|
||
|
|
|
||
|
|
c_RBTree_Destroy(&tree);
|
||
|
|
test_log("5. 紅黑樹資源徹底銷毀成功");
|
||
|
|
|
||
|
|
printf("\n==================================================\n");
|
||
|
|
printf(" 恭喜!包含 O(log N) Remove 在內的所有紅黑樹單元測試完美通過!\n");
|
||
|
|
printf("==================================================\n");
|
||
|
|
|
||
|
|
return 0;
|
||
|
|
}
|