【附C源码】二叉搜索树的C语言实现

【附C源码】二叉搜索树的C语言实现

前言

二叉搜索树(Binary Search Tree,BST)作为一种基础且重要的数据结构,在计算机科学领域有着广泛的应用。本文将介绍一种基于C语言的二叉搜索树实现方案,涵盖其核心原理、代码实现细节以及使用方式。

核心原理

二叉搜索树的核心性质在于:对于树中的任意节点,其左子树中所有节点的值均小于该节点的值,右子树中所有节点的值均大于该节点的值。这一性质保证了中序遍历二叉搜索树时,输出结果必然是有序的。

基于这一性质,二叉搜索树在平均情况下能够以 O(log n) 的时间复杂度完成插入、删除和查找操作。当然,在最坏情况下(如树退化为链表),时间复杂度会退化为 O(n),这也是后续需要引入平衡机制的原因。

数据结构定义

首先定义树节点和树结构体:

c 复制代码
typedef int Data;

typedef struct TreeNode {
    Data data;
    struct TreeNode* left;
    struct TreeNode* right;
} TreeNode;

typedef struct {
    TreeNode* root;
    int size;
} Tree;

此处采用 typedef int Data 的方式对数据类型进行抽象,便于后续扩展为其他类型。树结构体中维护 size 字段,使得获取节点数量的操作能够在 O(1) 时间内完成。

关键操作实现

节点插入

插入操作的核心逻辑是从根节点出发,根据待插入值与当前节点值的大小关系,决定向左子树或右子树递归查找,直至找到合适的空位置:

c 复制代码
bool treeInsert(Tree* t, Data val) {
    TreeNode* newNode = (TreeNode*)malloc(sizeof(TreeNode));
    newNode->data = val;
    newNode->left = NULL;
    newNode->right = NULL;
    
    if (!t->root) {
        t->root = newNode;
        t->size++;
        return true;
    }
    
    TreeNode* current = t->root;
    TreeNode* parent = NULL;
    
    while (current) {
        parent = current;
        if (val < current->data) {
            current = current->left;
        } else if (val > current->data) {
            current = current->right;
        } else {
            free(newNode);  // 重复值不插入
            return false;
        }
    }
    
    if (val < parent->data) {
        parent->left = newNode;
    } else {
        parent->right = newNode;
    }
    t->size++;
    return true;
}

该实现采用迭代方式而非递归,避免了函数调用栈的开销。同时,代码中明确处理了重复值的情况,保证树中不存在重复节点。

节点删除

删除操作是二叉搜索树中最复杂的操作,需要根据待删除节点的子节点数量分三种情况处理:

  1. 叶子节点:直接删除,无需额外操作
  2. 单子节点:用子节点替代被删除节点
  3. 双子节点:用右子树的最小值(或左子树的最大值)替代被删除节点,然后递归删除该最小值节点
c 复制代码
TreeNode* treeRemoveNode(TreeNode* node, Data val) {
    if (!node) return NULL;
    
    if (val < node->data) {
        node->left = treeRemoveNode(node->left, val);
    } else if (val > node->data) {
        node->right = treeRemoveNode(node->right, val);
    } else {
        if (!node->left) {
            TreeNode* temp = node->right;
            free(node);
            return temp;
        } else if (!node->right) {
            TreeNode* temp = node->left;
            free(node);
            return temp;
        }
        
        TreeNode* temp = treeFindMin(node->right);
        node->data = temp->data;
        node->right = treeRemoveNode(node->right, temp->data);
    }
    return node;
}

此处选择右子树的最小值作为替代节点,是因为该值必然大于左子树所有节点且小于右子树其余节点,满足二叉搜索树的性质。

树的遍历

三种基本遍历方式的递归实现:

c 复制代码
void treeInOrderNode(TreeNode* node) {
    if (!node) return;
    treeInOrderNode(node->left);
    printf("%d ", node->data);
    treeInOrderNode(node->right);
}

中序遍历的输出结果即为升序序列,这一特性在实际应用中经常被利用。前序遍历和后序遍历的实现结构类似,仅调整访问顺序即可。

可视化输出

为了便于调试和验证,实现了一个简单的树形打印函数:

c 复制代码
void treePrintNode(TreeNode* node, int depth) {
    if (!node) return;
    
    treePrintNode(node->right, depth + 1);
    
    for (int i = 0; i < depth; i++) {
        printf("    ");
    }
    printf("%d\n", node->data);
    
    treePrintNode(node->left, depth + 1);
}

该函数采用右-根-左的遍历顺序,配合缩进输出,使得树的结构能够直观地呈现在终端上。

内存管理

C语言不像高级语言具备自动垃圾回收机制,因此内存管理需要格外谨慎。本实现中,销毁树的操作采用后序遍历的顺序递归释放节点:

c 复制代码
void treeNodeDestroy(TreeNode* node) {
    if (!node) return;
    treeNodeDestroy(node->left);
    treeNodeDestroy(node->right);
    free(node);
}

必须确保子节点先于父节点释放,否则会导致内存泄漏或访问非法内存。

使用示例

以下是一个完整的使用示例:

c 复制代码
int main() {
    Tree* t = treeCreate();
    
    treeInsert(t, 50);
    treeInsert(t, 30);
    treeInsert(t, 70);
    treeInsert(t, 20);
    treeInsert(t, 40);
    
    treePrint(t);
    treeInOrder(t);
    
    printf("树高度: %d\n", treeHeight(t));
    printf("叶子节点数: %d\n", treeCountLeaves(t));
    
    treeRemove(t, 30);
    treePrint(t);
    
    treeDestroy(t);
    return 0;
}

性能分析

操作 平均时间复杂度 最坏时间复杂度
插入 O(log n) O(n)
删除 O(log n) O(n)
查找 O(log n) O(n)
遍历 O(n) O(n)

当数据以随机顺序插入时,树的高度接近 log n,各项操作效率较高。但如果数据已排序,树将退化为链表,此时需要考虑引入AVL树或红黑树等自平衡机制。

总结

本文介绍了一种完整的二叉搜索树C语言实现方案。该实现涵盖了树的基本操作,代码结构清晰,注释完整,适合作为数据结构学习的参考材料。对于生产环境的使用,建议在此基础上增加错误处理机制,并根据实际场景考虑是否需要引入平衡策略。

完整的代码实现可在文末获取,如有问题或建议,欢迎交流讨论。


⚠️源码地址:https://github.com/anjuxi/C-binary_search_-tree/tree/main

相关推荐
人间凡尔赛1 小时前
Next.js 16 生产级实战:Cache Components + View Transitions 完整指南
开发语言·javascript·ecmascript
可编程芯片开发3 小时前
基于MATLAB的PEF湍流风场生成器模拟与仿真
算法
罗西的思考4 小时前
【Agentic RL / 强化学习 / OPD】OpenClaw-RL 源码阅读笔记 --- (9)--- Reward Judging
人工智能·算法·机器学习
2401_841495644 小时前
【数据结构】B+树
数据结构·数据库·c++·b+树·概念·结构·操作原理
稚南城才子,乌衣巷风流5 小时前
函数:编程中的核心概念
开发语言·前端·javascript
阿米亚波5 小时前
【C++】流式数据输入处理(不完全整理)
开发语言·c++·笔记
Mr.HeBoYan5 小时前
一次持续三天才出现的丢包故障——深入解析 DPDK Memory Ordering、rte_ring 与 CPU Memory Barrier (下)
linux·网络·算法·架构·dpdk
大模型码小白5 小时前
JAVA 集合框架进阶:List 与 Set 的深度解析与实战
java·开发语言·人工智能·windows·语言模型·list·ai编程
wabs6666 小时前
关于图论【深度优先搜索的理论基础】
算法·深度优先·图论
皓月斯语6 小时前
【C++基础】三目运算符
开发语言·数据结构·c++