C语言实现二叉树数据结构超详细教程(图解+代码逐行分析)

#新星杯·14天创作挑战营·第10期#
前言

二叉树是计算机科学中最基础的树形数据结构之一,在数据库索引、文件系统等领域广泛应用。本文通过C语言实现包含插入、遍历等基本操作的二叉树,特别针对初学者设计,包含完整代码注释和遍历过程图解。


一、二叉树基础知识

核心特性

  • 每个节点最多有两个子节点(左/右子节点)

  • 特殊的树结构:二叉搜索树、平衡二叉树、满二叉树等

  • 常用遍历方式:广度优先(BFS)、深度优先(DFS)


二、代码结构解析
1. 节点结构定义

c

typedef struct Node {
    int key;            // 节点存储的值
    struct Node* lchild; // 左子节点指针
    struct Node* rchild; // 右子节点指针
} Node;

内存结构

+--------+--------+--------+
|  key   | lchild | rchild |
+--------+--------+--------+

2. 节点创建函数

c

Node* getNewNode(int key) {
    Node* p = (Node*)malloc(sizeof(Node));
    p->key = key;              // 设置节点值
    p->lchild = p->rchild = NULL; // 初始化子节点指针
    return p;
}

关键点

  • 使用malloc动态分配内存

  • 初始化时将子节点指针置为NULL


3. 插入操作(随机插入)

c

Node* insert(Node* root, int key) {
    if (root == NULL) return getNewNode(key); // 空树创建新节点
    
    // 随机选择插入方向(50%概率左右)
    if (rand() % 2) root->lchild = insert(root->lchild, key);
    else root->rchild = insert(root->rchild, key);
    
    return root;
}

插入逻辑

  1. 如果当前节点为空,创建新节点

  2. 通过随机数决定插入左/右子树

  3. 递归完成插入操作


4. 内存释放(后序遍历)

c

void clear(Node* root) {
    if (root == NULL) return;
    clear(root->lchild);  // 先释放左子树
    clear(root->rchild);  // 再释放右子树
    free(root);           // 最后释放当前节点
}

释放顺序
必须先释放子节点再释放父节点,避免访问已释放内存


三、遍历算法实现
1. 广度优先搜索(BFS)

c

#define MAX_NODE 10
Node* queue[MAX_NODE + 5]; // 循环队列
int head, tail;

void bfs(Node* root) {
    head = tail = 0;
    queue[tail++] = root; // 根节点入队
    
    while (head < tail) {
        Node* node = queue[head++]; // 取出队首节点
        
        printf("\nnode : %d\n", node->key);
        
        if (node->lchild) { // 左子节点入队
            queue[tail++] = node->lchild;
            printf("\t%d->%d (left)\n", node->key, node->lchild->key);
        }
        if (node->rchild) { // 右子节点入队
            queue[tail++] = node->rchild;
            printf("\t%d->%d (right)\n", node->key, node->rchild->key);
        }
    }
}

执行过程

队列状态变化:
[5] → [5,3] → [3,7] → ...
输出顺序:5 → 3 → 7 → ...

2. 深度优先搜索(DFS)

c

int tot = 0; // 全局计数器

void dfs(Node* root) {
    if (root == NULL) return;
    
    int start = ++tot; // 进入节点时记录起始位置
    
    if (root->lchild) dfs(root->lchild); // 递归左子树
    if (root->rchild) dfs(root->rchild); // 递归右子树
    
    int end = ++tot; // 离开节点时记录结束位置
    printf("%d : [%d, %d]\n", root->key, start, end);
}

访问顺序

示例树:
    5
   / \
  3   7
  
输出:
3 : [2, 3]
7 : [4, 5]
5 : [1, 6]

四、主函数测试

c

int main() {
    srand(time(0)); // 初始化随机种子
    Node* root = NULL;
    
    // 插入10个随机节点
    for (int i = 0; i < MAX_NODE; i++) {
        root = insert(root, rand() % 100);
    }
    
    bfs(root); // 广度优先遍历
    dfs(root); // 深度优先遍历
    
    clear(root); // 释放内存
    return 0;
}

五、运行结果分析

典型BFS输出

node : 56
    56->34 (left)
    56->78 (right)

node : 34
    34->12 (left)

node : 78
    ...

DFS输出示例

12 : [2, 3]
34 : [1, 4]
78 : [5, 8]
56 : [1, 9]

六、常见问题解答
  1. 为什么用随机插入?

    • 简化示例代码逻辑

    • 实际应用应根据需求选择插入策略(如二叉搜索树)

  2. DFS中的区间编号有什么意义?

    • 模拟树形结构的区间表示法

    • 可用于子树范围判断等场景

  3. 如何处理大型二叉树?

    • 使用动态队列替代静态数组

    • 递归深度过大时可改用迭代实现


七、总结与扩展

核心知识点

  • 二叉树节点的链式存储

  • 递归在树结构中的应用

  • BFS与DFS的实现差异

扩展方向

  1. 实现二叉搜索树

  2. 添加节点删除功能

  3. 实现平衡二叉树(AVL树)

相关练习:实现二叉树的高度计算、镜像翻转、路径查找

注:代码出自B站海贼胡船长

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

维维宝宝最可爱啦QWQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值