当你已经掌握了C语言的基础语法,能够编写简单的程序时,真正的挑战才刚刚开始。C语言进阶要求你深入理解内存管理、指针的高级用法、数据结构实现、编译链接过程、系统级编程等核心领域。本文将系统梳理C语言进阶开发的核心知识体系,涵盖指针深度剖析、动态内存管理、数据结构实现、文件系统操作、预处理高级技巧、多文件项目组织、系统调用等关键领域,助你突破瓶颈,成为一名真正精通C语言的开发者。
一、指针深度剖析:C语言的灵魂
1.1 多级指针与指针数组
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* 多级指针:指向指针的指针
* 应用场景:动态二维数组、函数参数中修改指针本身
*/
void multi_level_pointer_demo() {
int value = 100;
int *ptr = &value; // 一级指针
int **pptr = &ptr; // 二级指针
int ***ppptr = &pptr; // 三级指针
printf("value = %d\n", value);
printf("*ptr = %d\n", *ptr);
printf("**pptr = %d\n", **pptr);
printf("***ppptr = %d\n", ***ppptr);
// 修改值
***ppptr = 200;
printf("\n修改后 value = %d\n", value);
}
/**
* 指针数组 vs 数组指针
* 指针数组:数组元素是指针
* 数组指针:指向数组的指针
*/
void pointer_array_vs_array_pointer() {
// 1. 指针数组:存储指针的数组
int a = 10, b = 20, c = 30;
int *ptrArray[3] = {&a, &b, &c}; // 指针数组
printf("指针数组:\n");
for (int i = 0; i < 3; i++) {
printf("ptrArray[%d] = %d\n", i, *ptrArray[i]);
}
// 2. 数组指针:指向数组的指针
int arr[5] = {1, 2, 3, 4, 5};
int (*arrayPtr)[5] = &arr; // 指向包含5个int的数组
printf("\n数组指针:\n");
for (int i = 0; i < 5; i++) {
printf("(*arrayPtr)[%d] = %d\n", i, (*arrayPtr)[i]);
}
// 3. 字符串数组(指针数组的典型应用)
char *fruits[] = {"苹果", "香蕉", "橙子", "葡萄"};
int fruitCount = sizeof(fruits) / sizeof(fruits[0]);
printf("\n字符串数组:\n");
for (int i = 0; i < fruitCount; i++) {
printf("水果:%s\n", fruits[i]);
}
}
/**
* 函数指针的高级应用
*/
int add(int a, int b) { return a + b; }
int subtract(int a, int b) { return a - b; }
int multiply(int a, int b) { return a * b; }
int divide(int a, int b) { return b != 0 ? a / b : 0; }
// 函数指针作为参数(回调函数)
int calculate(int (*operation)(int, int), int x, int y) {
return operation(x, y);
}
// 返回函数指针的函数
typedef int (*Operation)(int, int);
Operation get_operation(char op) {
switch (op) {
case '+': return add;
case '-': return subtract;
case '*': return multiply;
case '/': return divide;
default: return NULL;
}
}
void function_pointer_demo() {
// 函数指针数组(计算器)
Operation ops[] = {add, subtract, multiply, divide};
char symbols[] = {'+', '-', '*', '/'};
printf("\n函数指针数组计算器:\n");
for (int i = 0; i < 4; i++) {
printf("10 %c 5 = %d\n", symbols[i], ops[i](10, 5));
}
// 动态选择操作
Operation op = get_operation('*');
printf("\n10 * 5 = %d\n", op(10, 5));
// 回调函数
printf("回调:5 + 3 = %d\n", calculate(add, 5, 3));
}
/**
* 指向函数的指针数组(状态机实现)
*/
typedef enum {
STATE_IDLE,
STATE_RUNNING,
STATE_PAUSED,
STATE_STOPPED
} State;
void handle_idle() { printf("空闲状态\n"); }
void handle_running() { printf("运行状态\n"); }
void handle_paused() { printf("暂停状态\n"); }
void handle_stopped() { printf("停止状态\n"); }
void state_machine_demo() {
void (*state_handlers[])(void) = {
handle_idle,
handle_running,
handle_paused,
handle_stopped
};
State current = STATE_RUNNING;
state_handlers[current](); // 调用对应处理函数
}
1.2 复杂指针声明解析
/**
* 复杂指针声明解析
* 规则:从变量名开始,先右后左,括号优先
*/
void complex_pointer_declaration() {
// 1. 指针数组:int *p[10] → p是数组,包含10个指向int的指针
int *p1[10];
// 2. 数组指针:int (*p)[10] → p是指针,指向包含10个int的数组
int (*p2)[10];
// 3. 函数指针:int (*p)(int, int) → p是指针,指向返回int、参数(int,int)的函数
int (*p3)(int, int);
// 4. 返回指针的函数:int* p(int) → p是函数,返回int*
int* p4(int);
// 5. 函数指针数组:int (*p[5])(int) → p是数组,元素是函数指针
int (*p5[5])(int);
// 6. 指向函数指针数组的指针:int (*(*p)[5])(int)
int (*(*p6)[5])(int);
// 使用cdecl工具解析复杂声明
// 安装:sudo apt install cdecl
// 使用:cdecl> explain "int (*(*foo)(int))[5]"
}
/**
* 使用typedef简化复杂声明
*/
typedef int (*OperationFunc)(int, int); // 函数指针类型
typedef int (*ArrayOfFuncs[10])(int, int); // 函数指针数组类型
typedef int (*FuncReturningArray())[10]; // 返回数组指针的函数
1.3 指针与const的深度结合
/**
* const与指针的组合
* const修饰的是它左边最近的内容,如果左边没有则修饰右边
*/
void const_pointer_demo() {
int a = 10, b = 20;
// 1. 指向常量的指针:不能通过指针修改值,但指针可以指向其他变量
const int *ptr1 = &a;
// *ptr1 = 30; // 错误!不能修改指向的值
ptr1 = &b; // 可以,指针可以重新指向
// 2. 常量指针:指针本身不能修改,但可以修改指向的值
int *const ptr2 = &a;
*ptr2 = 30; // 可以,修改指向的值
// ptr2 = &b; // 错误!指针不能重新指向
// 3. 指向常量的常量指针:都不能修改
const int *const ptr3 = &a;
// *ptr3 = 30; // 错误!
// ptr3 = &b; // 错误!
// 4. const在函数参数中的应用
// void print_array(const int arr[], int size) // 保证不修改数组
// const char *str // 字符串常量,常用于函数参数
}
/**
* 常量字符串与字符数组的区别
*/
void string_const_demo() {
// 字符串常量:存储在只读数据段,不能修改
const char *str1 = "Hello World";
// str1[0] = 'h'; // 错误!字符串常量不能修改
// 字符数组:存储在栈上,可以修改
char str2[] = "Hello World";
str2[0] = 'h'; // 正确
printf("修改后:%s\n", str2);
// 字符串常量池
const char *s1 = "Hello";
const char *s2 = "Hello";
printf("s1和s2指向同一地址?%s\n", s1 == s2 ? "是" : "否"); // 通常为"是"
}
二、动态内存管理深入
2.1 内存布局与分配策略
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* C程序内存布局
*
* 栈(Stack):局部变量、函数参数、返回地址,向下增长
* 堆(Heap):动态分配的内存,向上增长
* 数据段(Data Segment):
* - .data:已初始化的全局变量和静态变量
* - .bss:未初始化的全局变量和静态变量(自动初始化为0)
* 代码段(Text Segment):可执行代码,只读
*/
// 全局变量(数据段 .data)
int global_init = 100;
// 未初始化全局变量(数据段 .bss)
int global_uninit;
// 静态变量(数据段 .data)
static int static_var = 50;
void memory_layout_demo() {
// 局部变量(栈)
int local_var = 10;
int *heap_var = (int*)malloc(sizeof(int));
printf("代码段地址:%p\n", (void*)memory_layout_demo);
printf("全局变量地址:%p\n", (void*)&global_init);
printf("静态变量地址:%p\n", (void*)&static_var);
printf("局部变量地址:%p\n", (void*)&local_var);
printf("堆变量地址:%p\n", (void*)heap_var);
free(heap_var);
}
/**
* 内存对齐与结构体大小
*/
struct __attribute__((packed)) PackedStruct {
char c; // 1字节
int i; // 4字节
short s; // 2字节
}; // 不按对齐规则,大小为7
struct NormalStruct {
char c; // 1 + 3填充
int i; // 4
short s; // 2 + 2填充
}; // 大小12字节
void memory_alignment_demo() {
printf("PackedStruct大小:%zu\n", sizeof(struct PackedStruct));
printf("NormalStruct大小:%zu\n", sizeof(struct NormalStruct));
// 查看偏移量
struct NormalStruct ns;
printf("偏移量 c: %zu\n", offsetof(struct NormalStruct, c));
printf("偏移量 i: %zu\n", offsetof(struct NormalStruct, i));
printf("偏移量 s: %zu\n", offsetof(struct NormalStruct, s));
}
2.2 内存池实现
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/**
* 内存池(Memory Pool)
* 预分配大块内存,自定义分配策略,减少malloc/free调用
*/
typedef struct MemoryBlock {
void *start;
size_t size;
size_t used;
struct MemoryBlock *next;
} MemoryBlock;
typedef struct MemoryPool {
MemoryBlock *first_block;
size_t block_size;
} MemoryPool;
// 创建内存池
MemoryPool* mempool_create(size_t block_size) {
MemoryPool *pool = (MemoryPool*)malloc(sizeof(MemoryPool));
if (!pool) return NULL;
pool->first_block = NULL;
pool->block_size = block_size;
return pool;
}
// 分配新块
static MemoryBlock* mempool_alloc_block(MemoryPool *pool) {
MemoryBlock *block = (MemoryBlock*)malloc(sizeof(MemoryBlock));
if (!block) return NULL;
block->start = malloc(pool->block_size);
if (!block->start) {
free(block);
return NULL;
}
block->size = pool->block_size;
block->used = 0;
block->next = pool->first_block;
pool->first_block = block;
return block;
}
// 从内存池分配内存
void* mempool_alloc(MemoryPool *pool, size_t size) {
if (!pool) return NULL;
// 对齐到8字节
size = (size + 7) & ~7;
// 查找有足够空间的块
MemoryBlock *block = pool->first_block;
while (block) {
if (block->size - block->used >= size) {
void *ptr = (char*)block->start + block->used;
block->used += size;
return ptr;
}
block = block->next;
}
// 没有足够空间,分配新块
block = mempool_alloc_block(pool);
if (!block) return NULL;
if (block->size - block->used >= size) {
void *ptr = (char*)block->start + block->used;
block->used += size;
return ptr;
}
return NULL; // 单个块不够大
}
// 释放内存池(一次性释放所有内存)
void mempool_destroy(MemoryPool *pool) {
if (!pool) return;
MemoryBlock *block = pool->first_block;
while (block) {
MemoryBlock *next = block->next;
free(block->start);
free(block);
block = next;
}
free(pool);
}
// 测试内存池
void memory_pool_demo() {
MemoryPool *pool = mempool_create(1024 * 1024); // 1MB块
int *arr = (int*)mempool_alloc(pool, 100 * sizeof(int));
char *str = (char*)mempool_alloc(pool, 256);
// 使用内存...
for (int i = 0; i < 100; i++) {
arr[i] = i;
}
strcpy(str, "Hello from memory pool!");
printf("%s\n", str);
mempool_destroy(pool); // 一次性释放所有
}
2.3 内存泄漏检测
#include <stdio.h>
#include <stdlib.h>
/**
* 简单的内存泄漏检测工具
*/
typedef struct Allocation {
void *ptr;
size_t size;
const char *file;
int line;
struct Allocation *next;
} Allocation;
static Allocation *allocations = NULL;
static size_t total_allocated = 0;
void* track_malloc(size_t size, const char *file, int line) {
void *ptr = malloc(size);
if (ptr) {
Allocation *alloc = (Allocation*)malloc(sizeof(Allocation));
alloc->ptr = ptr;
alloc->size = size;
alloc->file = file;
alloc->line = line;
alloc->next = allocations;
allocations = alloc;
total_allocated += size;
}
return ptr;
}
void track_free(void *ptr) {
Allocation **curr = &allocations;
while (*curr) {
if ((*curr)->ptr == ptr) {
Allocation *to_free = *curr;
*curr = (*curr)->next;
total_allocated -= to_free->size;
free(to_free);
break;
}
curr = &((*curr)->next);
}
free(ptr);
}
void print_memory_report() {
if (allocations) {
printf("内存泄漏检测报告:\n");
printf("================================\n");
Allocation *curr = allocations;
while (curr) {
printf("泄漏:%p 大小 %zu 字节 (分配于 %s:%d)\n",
curr->ptr, curr->size, curr->file, curr->line);
curr = curr->next;
}
printf("总泄漏内存:%zu 字节\n", total_allocated);
} else {
printf("无内存泄漏\n");
}
}
// 使用宏替换malloc和free
#define malloc(size) track_malloc(size, __FILE__, __LINE__)
#define free(ptr) track_free(ptr)
void memory_leak_test() {
int *leak1 = (int*)malloc(100 * sizeof(int));
int *leak2 = (int*)malloc(200 * sizeof(int));
free(leak1);
// leak2 没有释放
}
// 注意:需要在main函数最后调用print_memory_report()
三、数据结构实现
3.1 链表(单链表、双链表、循环链表)
#include <stdio.h>
#include <stdlib.h>
// 单链表节点
typedef struct Node {
int data;
struct Node *next;
} Node;
// 创建节点
Node* create_node(int data) {
Node *new_node = (Node*)malloc(sizeof(Node));
if (!new_node) return NULL;
new_node->data = data;
new_node->next = NULL;
return new_node;
}
// 单链表操作
typedef struct LinkedList {
Node *head;
Node *tail;
size_t size;
} LinkedList;
void linkedlist_init(LinkedList *list) {
list->head = NULL;
list->tail = NULL;
list->size = 0;
}
void linkedlist_push_front(LinkedList *list, int data) {
Node *new_node = create_node(data);
if (!new_node) return;
new_node->next = list->head;
list->head = new_node;
if (!list->tail) {
list->tail = new_node;
}
list->size++;
}
void linkedlist_push_back(LinkedList *list, int data) {
Node *new_node = create_node(data);
if (!new_node) return;
if (!list->tail) {
list->head = new_node;
list->tail = new_node;
} else {
list->tail->next = new_node;
list->tail = new_node;
}
list->size++;
}
void linkedlist_insert(LinkedList *list, int index, int data) {
if (index < 0 || index > list->size) return;
if (index == 0) {
linkedlist_push_front(list, data);
return;
}
if (index == list->size) {
linkedlist_push_back(list, data);
return;
}
Node *new_node = create_node(data);
if (!new_node) return;
Node *curr = list->head;
for (int i = 0; i < index - 1; i++) {
curr = curr->next;
}
new_node->next = curr->next;
curr->next = new_node;
list->size++;
}
int linkedlist_pop_front(LinkedList *list) {
if (!list->head) return 0;
Node *to_free = list->head;
int data = to_free->data;
list->head = list->head->next;
if (!list->head) {
list->tail = NULL;
}
free(to_free);
list->size--;
return data;
}
void linkedlist_print(LinkedList *list) {
Node *curr = list->head;
while (curr) {
printf("%d -> ", curr->data);
curr = curr->next;
}
printf("NULL\n");
}
void linkedlist_free(LinkedList *list) {
Node *curr = list->head;
while (curr) {
Node *next = curr->next;
free(curr);
curr = next;
}
list->head = NULL;
list->tail = NULL;
list->size = 0;
}
// 双链表节点
typedef struct DNode {
int data;
struct DNode *prev;
struct DNode *next;
} DNode;
typedef struct DoublyLinkedList {
DNode *head;
DNode *tail;
size_t size;
} DoublyLinkedList;
void dlist_push_back(DoublyLinkedList *list, int data) {
DNode *new_node = (DNode*)malloc(sizeof(DNode));
if (!new_node) return;
new_node->data = data;
new_node->prev = list->tail;
new_node->next = NULL;
if (list->tail) {
list->tail->next = new_node;
} else {
list->head = new_node;
}
list->tail = new_node;
list->size++;
}
void dlist_print_forward(DoublyLinkedList *list) {
DNode *curr = list->head;
while (curr) {
printf("%d <-> ", curr->data);
curr = curr->next;
}
printf("NULL\n");
}
void dlist_print_backward(DoublyLinkedList *list) {
DNode *curr = list->tail;
while (curr) {
printf("%d <-> ", curr->data);
curr = curr->prev;
}
printf("NULL\n");
}
void linkedlist_demo() {
LinkedList list;
linkedlist_init(&list);
linkedlist_push_back(&list, 10);
linkedlist_push_back(&list, 20);
linkedlist_push_front(&list, 5);
linkedlist_insert(&list, 2, 15);
printf("单链表:");
linkedlist_print(&list);
printf("大小:%zu\n", list.size);
linkedlist_pop_front(&list);
printf("弹出头部后:");
linkedlist_print(&list);
linkedlist_free(&list);
}
3.2 栈与队列
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
// 栈(数组实现)
typedef struct Stack {
int *data;
int top;
int capacity;
} Stack;
Stack* stack_create(int capacity) {
Stack *s = (Stack*)malloc(sizeof(Stack));
if (!s) return NULL;
s->data = (int*)malloc(capacity * sizeof(int));
if (!s->data) {
free(s);
return NULL;
}
s->top = -1;
s->capacity = capacity;
return s;
}
bool stack_is_empty(Stack *s) {
return s->top == -1;
}
bool stack_is_full(Stack *s) {
return s->top == s->capacity - 1;
}
void stack_push(Stack *s, int value) {
if (stack_is_full(s)) {
// 动态扩容
s->capacity *= 2;
s->data = (int*)realloc(s->data, s->capacity * sizeof(int));
if (!s->data) return;
}
s->data[++s->top] = value;
}
int stack_pop(Stack *s) {
if (stack_is_empty(s)) return 0;
return s->data[s->top--];
}
int stack_peek(Stack *s) {
if (stack_is_empty(s)) return 0;
return s->data[s->top];
}
void stack_free(Stack *s) {
if (s) {
free(s->data);
free(s);
}
}
// 队列(循环数组实现)
typedef struct Queue {
int *data;
int front;
int rear;
int capacity;
int size;
} Queue;
Queue* queue_create(int capacity) {
Queue *q = (Queue*)malloc(sizeof(Queue));
if (!q) return NULL;
q->data = (int*)malloc(capacity * sizeof(int));
if (!q->data) {
free(q);
return NULL;
}
q->front = 0;
q->rear = 0;
q->capacity = capacity;
q->size = 0;
return q;
}
bool queue_is_empty(Queue *q) {
return q->size == 0;
}
bool queue_is_full(Queue *q) {
return q->size == q->capacity;
}
void queue_enqueue(Queue *q, int value) {
if (queue_is_full(q)) {
// 动态扩容
int new_capacity = q->capacity * 2;
int *new_data = (int*)malloc(new_capacity * sizeof(int));
if (!new_data) return;
// 重新排列元素
for (int i = 0; i < q->size; i++) {
new_data[i] = q->data[(q->front + i) % q->capacity];
}
free(q->data);
q->data = new_data;
q->front = 0;
q->rear = q->size;
q->capacity = new_capacity;
}
q->data[q->rear] = value;
q->rear = (q->rear + 1) % q->capacity;
q->size++;
}
int queue_dequeue(Queue *q) {
if (queue_is_empty(q)) return 0;
int value = q->data[q->front];
q->front = (q->front + 1) % q->capacity;
q->size--;
return value;
}
void queue_free(Queue *q) {
if (q) {
free(q->data);
free(q);
}
}
// 栈应用:括号匹配
bool is_balanced(const char *str) {
Stack *s = stack_create(100);
for (int i = 0; str[i] != '\0'; i++) {
char c = str[i];
if (c == '(' || c == '[' || c == '{') {
stack_push(s, c);
} else if (c == ')' || c == ']' || c == '}') {
if (stack_is_empty(s)) {
stack_free(s);
return false;
}
char top = stack_pop(s);
if ((c == ')' && top != '(') ||
(c == ']' && top != '[') ||
(c == '}' && top != '{')) {
stack_free(s);
return false;
}
}
}
bool result = stack_is_empty(s);
stack_free(s);
return result;
}
void stack_queue_demo() {
Stack *s = stack_create(10);
stack_push(s, 1);
stack_push(s, 2);
stack_push(s, 3);
printf("栈弹出:%d\n", stack_pop(s));
printf("栈顶:%d\n", stack_peek(s));
stack_free(s);
Queue *q = queue_create(3);
queue_enqueue(q, 10);
queue_enqueue(q, 20);
queue_enqueue(q, 30);
queue_enqueue(q, 40); // 扩容
printf("队列弹出:%d\n", queue_dequeue(q));
queue_free(q);
printf("括号匹配 '([{}])':%s\n", is_balanced("([{}])") ? "匹配" : "不匹配");
printf("括号匹配 '([)]':%s\n", is_balanced("([)]") ? "匹配" : "不匹配");
}
3.3 二叉树与遍历
#include <stdio.h>
#include <stdlib.h>
// 二叉树节点
typedef struct TreeNode {
int data;
struct TreeNode *left;
struct TreeNode *right;
} TreeNode;
// 创建节点
TreeNode* create_node(int data) {
TreeNode *node = (TreeNode*)malloc(sizeof(TreeNode));
if (!node) return NULL;
node->data = data;
node->left = NULL;
node->right = NULL;
return node;
}
// 插入二叉搜索树
TreeNode* bst_insert(TreeNode *root, int data) {
if (root == NULL) {
return create_node(data);
}
if (data < root->data) {
root->left = bst_insert(root->left, data);
} else if (data > root->data) {
root->right = bst_insert(root->right, data);
}
return root;
}
// 查找节点
TreeNode* bst_search(TreeNode *root, int data) {
if (root == NULL || root->data == data) {
return root;
}
if (data < root->data) {
return bst_search(root->left, data);
}
return bst_search(root->right, data);
}
// 查找最小值
TreeNode* bst_find_min(TreeNode *root) {
while (root && root->left) {
root = root->left;
}
return root;
}
// 删除节点
TreeNode* bst_delete(TreeNode *root, int data) {
if (root == NULL) return NULL;
if (data < root->data) {
root->left = bst_delete(root->left, data);
} else if (data > root->data) {
root->right = bst_delete(root->right, data);
} else {
// 找到要删除的节点
if (root->left == NULL) {
TreeNode *temp = root->right;
free(root);
return temp;
} else if (root->right == NULL) {
TreeNode *temp = root->left;
free(root);
return temp;
}
// 有两个子节点:找到右子树的最小节点
TreeNode *min_node = bst_find_min(root->right);
root->data = min_node->data;
root->right = bst_delete(root->right, min_node->data);
}
return root;
}
// 前序遍历(根-左-右)
void preorder_traversal(TreeNode *root) {
if (root) {
printf("%d ", root->data);
preorder_traversal(root->left);
preorder_traversal(root->right);
}
}
// 中序遍历(左-根-右)——二叉搜索树得到有序序列
void inorder_traversal(TreeNode *root) {
if (root) {
inorder_traversal(root->left);
printf("%d ", root->data);
inorder_traversal(root->right);
}
}
// 后序遍历(左-右-根)
void postorder_traversal(TreeNode *root) {
if (root) {
postorder_traversal(root->left);
postorder_traversal(root->right);
printf("%d ", root->data);
}
}
// 层序遍历(使用队列)
void levelorder_traversal(TreeNode *root) {
if (!root) return;
// 简单队列实现
TreeNode *queue[100];
int front = 0, rear = 0;
queue[rear++] = root;
while (front < rear) {
TreeNode *node = queue[front++];
printf("%d ", node->data);
if (node->left) queue[rear++] = node->left;
if (node->right) queue[rear++] = node->right;
}
}
// 计算树的高度
int tree_height(TreeNode *root) {
if (root == NULL) return 0;
int left_height = tree_height(root->left);
int right_height = tree_height(root->right);
return (left_height > right_height ? left_height : right_height) + 1;
}
// 释放树
void tree_free(TreeNode *root) {
if (root) {
tree_free(root->left);
tree_free(root->right);
free(root);
}
}
void binary_tree_demo() {
TreeNode *root = NULL;
int values[] = {50, 30, 70, 20, 40, 60, 80, 10, 25, 35, 45};
int n = sizeof(values) / sizeof(values[0]);
for (int i = 0; i < n; i++) {
root = bst_insert(root, values[i]);
}
printf("前序遍历:");
preorder_traversal(root);
printf("\n");
printf("中序遍历:");
inorder_traversal(root);
printf("\n");
printf("后序遍历:");
postorder_traversal(root);
printf("\n");
printf("层序遍历:");
levelorder_traversal(root);
printf("\n");
printf("树的高度:%d\n", tree_height(root));
printf("查找40:%s\n", bst_search(root, 40) ? "找到" : "未找到");
root = bst_delete(root, 50);
printf("删除50后中序遍历:");
inorder_traversal(root);
printf("\n");
tree_free(root);
}