C语言进阶知识概览(一)

简介: 教程来源 https://app-adtysnu98v0h.appmiaoda.com 系统梳理C语言进阶核心知识:深度剖析多级指针、函数指针与const组合;详解动态内存管理、内存池及泄漏检测;实现链表、栈、队列、二叉搜索树等数据结构;涵盖内存布局、文件I/O、预处理与系统编程,助你突破瓶颈,成为真正精通C的开发者。

当你已经掌握了C语言的基础语法,能够编写简单的程序时,真正的挑战才刚刚开始。C语言进阶要求你深入理解内存管理、指针的高级用法、数据结构实现、编译链接过程、系统级编程等核心领域。本文将系统梳理C语言进阶开发的核心知识体系,涵盖指针深度剖析、动态内存管理、数据结构实现、文件系统操作、预处理高级技巧、多文件项目组织、系统调用等关键领域,助你突破瓶颈,成为一名真正精通C语言的开发者。
13f32e75-a8de-4be2-8800-387ce68cf0e4.png

一、指针深度剖析: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);
}

来源:
https://app-adtysnu98v0h.appmiaoda.com

相关文章
|
网络协议 算法 Java
|
7月前
|
人工智能 监控 安全
AI智能体的开发流程
开发AI智能体是从“调用模型”迈向“系统工程”的跃迁,强调感知-决策-执行闭环。涵盖目标拆解、四层架构(Brain/Planning/Memory/Tools)、工具集成、提示词工程、迭代评估与安全部署。非万能方案,固定流程仍宜用传统逻辑。
|
7月前
|
人工智能 JavaScript Linux
OpenClaw从部署到上手实战指南:阿里云+本地部署、百炼API配置、首次任务实操全攻略
2026年,OpenClaw(Clawdbot)作为开源AI生产力工具的代表,凭借跨平台部署、灵活的任务执行能力,成为普通人提升效率、落地AI应用的核心工具。很多用户历经波折完成安装、解决报错、成功启动系统后,却会对着界面陷入迷茫——不知道下一步该做什么。其实问题的核心从不是“不会用”,而是“没有给工具一个明确的任务”。OpenClaw的价值从不是简单的问答,而是帮你完整完成一件事,而装好后的第一件事,从来不是啃文档、研究配置,而是立刻让它完成一个简单的小任务。
983 1
|
监控 安全 生物认证
微信怎么一天加500人不限制呢?有没有方法
微信作为主流社交平台,为维护用户体验和防止营销骚扰,设置了严格的好友添加限制: 普通用户每日主动添加上限约20-30人
|
数据可视化
基于MATLAB的OFDM调制发射与接收仿真
基于MATLAB的OFDM调制发射与接收仿真
|
9月前
|
Ubuntu Linux Anolis
docker/脚本/ISO镜像安装FreeSWITCH 1.10.12 图形化界面
本文详解FreeSWITCH三种部署方式:脚本安装(推荐生产环境)、系统镜像(开箱即用)、容器化(适用于测试)。支持AlmaLinux、Rocky Linux、国产麒麟等系统,涵盖硬件要求、安装步骤与安全建议,助力高效搭建企业通信平台。
1718 6
|
Java
Alibaba Java Coding Guidelines
We are pleased to present Alibaba Java Coding Guidelines, which consolidates the best programming practices over the years from Alibaba Group's technical teams.
4084 0
|
Android开发 C++
【Android NDK 开发】在 C 代码中获取 Android 系统信息 ( NDK 项目创建 | NDK 配置 | 获取 Android 系统版本号 )(二)
【Android NDK 开发】在 C 代码中获取 Android 系统信息 ( NDK 项目创建 | NDK 配置 | 获取 Android 系统版本号 )(二)
2372 0
【Android NDK 开发】在 C 代码中获取 Android 系统信息 ( NDK 项目创建 | NDK 配置 | 获取 Android 系统版本号 )(二)
|
安全
【阿里云电脑】老机型玩黑神话,不听显卡嗡嗡转
万众瞩目的《黑神话:悟空》终于发布!作为一款采用虚幻5引擎的佳作,其画质令人惊艳。官方建议配置为i5-8400/Ryzen 5 1600+GTX 1060/RX 580起步,而推荐配置则为i7-9700/Ryzen 5 5500+RTX 2060/RX 5700 XT/Arc A750。虽然兼容性广泛,但仍有玩家因设备问题无法体验。PS5价格飙升至4200+,让人望而却步。此时,云主机成为理想选择:安全、便捷、经济,最低只需1.2元/小时,内置游戏官方镜像,即刻畅玩,同时支持多种用途。
1101 2
|
算法
时间(空间)复杂度(结构篇)
时间(空间)复杂度(结构篇)
552 6