数据结构 ——BST 树

一、引言

在有序数据的查找、插入与删除操作中,普通线性表的效率往往难以满足高效处理需求。二叉查找树(Binary Search Tree,简称BST)作为一种基础且重要的树形数据结构,通过严格的大小约束规则,将动态集合的操作效率从线性级别提升至对数级别,成为计算机科学中实现有序映射、有序集合、索引结构的核心工具。本文将围绕 BST 树的定义、性质、操作、实现与应用,系统介绍这一经典数据结构。

二、BST 树的定义与性质

1. 基本定义

二叉查找树(BST)是一棵具有以下性质的二叉树:

  • 若左子树非空,则左子树上所有节点的值均小于根节点的值
  • 若右子树非空,则右子树上所有节点的值均大于根节点的值
  • 左、右子树也分别是二叉查找树;
  • 通常不允许键值重复(若允许需明确规则)。

2. 核心性质

  1. 中序遍历有序 :对 BST 进行中序遍历 ,可得到一个递增的有序序列,这是 BST 最关键的特征。
  2. 分层比较:任何节点与其左右孩子满足 "左小右大",查找路径可通过大小比较快速确定。
  3. 效率依赖树高 :理想情况下为平衡树,操作效率为O(log n) ;最坏情况退化为链表,效率为O(n)

三、BST 树的基本结构

BST 的每个节点包含三部分信息:

  1. 关键字(数据域);
  2. 指向左孩子的指针;
  3. 指向右孩子的指针。

节点结构可表示为:

bash 复制代码
+----------------+
| left | key | right |
+----------------+

四、BST 树的核心操作

BST 的三大基础操作为:查找、插入、删除,全部遵循 "左小右大" 规则。

1. 查找操作

  • 从根节点开始:
    • 若当前节点值 == 目标值 → 查找成功;
    • 若目标值 < 当前节点值 → 进入左子树;
    • 若目标值 > 当前节点值 → 进入右子树;
  • 走到空节点 → 查找失败。

2. 插入操作

  • 按照查找路径走到应插入的空位置
  • 创建新节点,连接到父节点的左或右指针;
  • 插入过程不会改变已有结构,只新增叶子节点。

3. 删除操作(最复杂)

分三种情况:

  1. 删除叶子节点:直接删除,置空父节点指针。
  2. 删除仅有一个孩子的节点:用其子节点替代该节点。
  3. 删除有两个孩子的节点
    • 找到前驱 (左子树最大值)或后继(右子树最小值);
    • 用前驱 / 后继的值覆盖待删节点;
    • 删除前驱 / 后继节点。

4. 遍历操作

  • 前序遍历:根 → 左 → 右
  • 中序遍历:左 → 根 → 右(得到递增序列)
  • 后序遍历:左 → 右 → 根
  • 层序遍历:按层次从上到下(借助队列)

五、BST 树的 C 语言实现

以下给出可直接运行的 BST 完整代码:

cpp 复制代码
#include <stdio.h>
#include <stdlib.h>

// BST节点结构
typedef struct Node {
    int key;
    struct Node *left, *right;
} Node;

// 创建新节点
Node* createNode(int key) {
    Node* node = (Node*)malloc(sizeof(Node));
    node->key = key;
    node->left = node->right = NULL;
    return node;
}

// 插入节点
Node* insert(Node* root, int key) {
    if (root == NULL) return createNode(key);
    if (key < root->key)
        root->left = insert(root->left, key);
    else if (key > root->key)
        root->right = insert(root->right, key);
    return root;
}

// 查找节点
Node* search(Node* root, int key) {
    if (root == NULL || root->key == key)
        return root;
    if (key < root->key)
        return search(root->left, key);
    return search(root->right, key);
}

// 找最小值节点(用于删除)
Node* minNode(Node* root) {
    Node* cur = root;
    while (cur && cur->left != NULL)
        cur = cur->left;
    return cur;
}

// 删除节点
Node* delete(Node* root, int key) {
    if (root == NULL) return NULL;

    if (key < root->key)
        root->left = delete(root->left, key);
    else if (key > root->key)
        root->right = delete(root->right, key);
    else {
        // 1. 单/无子节点
        if (root->left == NULL) {
            Node* temp = root->right;
            free(root);
            return temp;
        }
        if (root->right == NULL) {
            Node* temp = root->left;
            free(root);
            return temp;
        }
        // 2. 双孩子节点:用后继替换
        Node* temp = minNode(root->right);
        root->key = temp->key;
        root->right = delete(root->right, temp->key);
    }
    return root;
}

// 中序遍历(输出有序序列)
void inOrder(Node* root) {
    if (root == NULL) return;
    inOrder(root->left);
    printf("%d ", root->key);
    inOrder(root->right);
}

int main() {
    Node* root = NULL;
    int arr[] = {50, 30, 70, 20, 40, 60, 80};
    int n = sizeof(arr)/sizeof(arr[0]);

    for (int i = 0; i < n; i++)
        root = insert(root, arr[i]);

    printf("中序遍历(递增):");
    inOrder(root);
    printf("\n");

    root = delete(root, 50);
    printf("删除50后:");
    inOrder(root);

    return 0;
}

六、BST 树的优缺点

优点

  1. 中序天然有序,无需额外排序;
  2. 动态操作高效:插入、删除、查找均无需移动大量元素;
  3. 实现简单,逻辑清晰,适合教学与基础工程使用。

缺点

  1. 容易退化:数据有序插入时退化成链表,效率变为 O (n);
  2. 无自平衡能力:需要 AVL、红黑树等改进结构保证效率。

七、BST 树的典型应用

  1. 有序集合与有序映射 :如 C++set/map底层(红黑树);
  2. 数据库索引:用于构建简单索引,加速范围查询;
  3. 排序算法:BST 排序等价于中序遍历,时间复杂度 O (n log n)~O (n²);
  4. 符号表:编译器、解释器用于管理变量名、函数名。

八、总结

二叉查找树(BST)是连接线性结构与平衡树形结构的关键桥梁。它基于 "左小右大" 的约束规则,实现了高效的动态有序操作,是理解 AVL 树、红黑树、B 树、B + 树的基础。尽管 BST 在极端情况下会退化,但其思想简洁、应用广泛,是数据结构中必须掌握的核心内容。

掌握 BST 的查找、插入、删除 三大操作与中序有序特性,就能真正理解动态查找结构的设计精髓,为后续学习更高级的平衡树与存储引擎打下坚实基础。

相关推荐
江屿风1 小时前
C++图的基本概念流食般投喂-竞赛编
开发语言·数据结构·c++·笔记·算法·图论
Byte不洛1 小时前
哈希表原理 + 冲突解决 + C++实现
数据结构·c++·算法·哈希算法·散列表
_日拱一卒10 小时前
LeetCode:994腐烂的橘子
java·数据结构·算法·leetcode·深度优先
2401_8685347813 小时前
【无标题】
数据结构·r语言
Mr. zhihao13 小时前
Redis五大高级数据结构:原理-场景-底层-横向对比
数据结构·redis
QiLinkOS13 小时前
【从实验室到商业战场:发明专利如何重塑科技与企业的共生生态】
大数据·c语言·数据结构·c++·人工智能·单片机·算法
如此这般英俊13 小时前
手撕Claude Code—第一章 agent-loop
数据结构·人工智能·语言模型·自然语言处理
过期动态15 小时前
【LeetCode 热题 100】接雨水
java·数据结构·算法·leetcode·职场和发展
青山师15 小时前
动态规划算法深度解析:从状态转移方程到工业级优化
数据结构·算法·面试·动态规划·代理模式·java面试