跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客GitHub 精选镜像工具UI配色美学隐私政策关于联系
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
C++算法

二叉搜索树深度解析:原理、实现与算法应用

二叉搜索树(BST)利用键值有序性实现高效增删查。核心性质是中序遍历即升序。本文详解其迭代式 C++ 实现,重点剖析删除节点时的替代策略及指针处理。对比了 BST 与有序数组二分查找的性能差异,并总结了 Key 与 Key-Value 两种搜索模型。结合经典算法题,如 BST 转双向链表、遍历序列构造二叉树及非递归遍历,深入讲解递归、栈及指针操作的实战技巧,帮助开发者巩固树结构核心知识。

岁月神偷发布于 2026/3/16更新于 2026/6/2319 浏览
二叉搜索树深度解析:原理、实现与算法应用

概述

二叉搜索树(Binary Search Tree,简称 BST)是计算机科学中一种重要的树形数据结构。它利用键值的有序性,高效支持数据的插入、删除和查找操作,是许多复杂算法的基础组件。

核心性质在于:若左子树不为空,则所有节点值小于根节点;若右子树不为空,则所有节点值大于根节点。左右子树也均为二叉搜索树。这意味着中序遍历的结果必然是升序序列。

核心实现

下面展示基于 C++ 的迭代式实现。相比递归,迭代法在处理深层树时能避免栈溢出风险,更适合生产环境。

template <class K>
struct BSTreeNode {
    BSTreeNode<K>* _left;
    BSTreeNode<K>* _right;
    K _key;
    BSTreeNode(const K& key) : _left(nullptr), _right(nullptr), _key(key) {}
};

template <class K>
class BSTree {
    typedef BSTreeNode<K> Node;
public:
    BSTree() : _root(nullptr) {}
    ~BSTree() { Destroy(_root); }
    
    bool Insert(const K& key) {
        if (_root == nullptr) {
            _root = new Node(key);
            return true;
        }
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur) {
            if (key > cur->_key) {
                parent = cur;
                cur = cur->_right;
            } else if (key < cur->_key) {
                parent = cur;
                cur = cur->_left;
            } else {
                return false; // 不允许重复
            }
        }
        cur = new Node(key);
        if (key > parent->_key)
            parent->_right = cur;
        else
            parent->_left = cur;
        return true;
    }
    
    bool Find(const K& key) {
        Node* cur = _root;
        while (cur) {
            if (key > cur->_key) cur = cur->_right;
            else if (key < cur->_key) cur = cur->_left;
            else return true;
        }
        return false;
    }
    
    bool Erase(const K& key) {
        Node* parent = nullptr;
        Node* cur = _root;
        while (cur) {
            if (key > cur->_key) {
                parent = cur;
                cur = cur->_right;
            } else if (key < cur->_key) {
                parent = cur;
                cur = cur->_left;
            } else {
                // 找到目标节点,分情况处理
                if (cur->_left == nullptr) {
                    if (cur == _root) _root = cur->_right;
                    else if (parent->_right == cur) parent->_right = cur->_right;
                    else parent->_left = cur->_right;
                } else if (cur->_right == nullptr) {
                    if (cur == _root) _root = cur->_left;
                    else if (parent->_right == cur) parent->_right = cur->_left;
                    else parent->_left = cur->_left;
                } else {
                    // 左右都不为空,找左子树最大值替换
                    Node* leftMaxParent = cur;
                    Node* leftMax = cur->_left;
                    while (leftMax->_right) {
                        leftMaxParent = leftMax;
                        leftMax = leftMax->_right;
                    }
                    swap(cur->_key, leftMax->_key);
                    if (leftMaxParent->_left == leftMax)
                        leftMaxParent->_left = leftMax->_left;
                    else
                        leftMaxParent->_right = leftMax->_left;
                    delete leftMax;
                    return true;
                }
                delete cur;
                return true;
            }
        }
        return false;
    }
    
private:
    void Destroy(Node*& root) {
        if (!root) return;
        Destroy(root->_left);
        Destroy(root->_right);
        delete root;
        root = nullptr;
    }
    Node* _root;
};

注意删除操作是难点。当节点有两个子节点时,通常用左子树的最大值或右子树的最小值替换当前节点的值,然后删除那个替代节点。这样既保持了 BST 性质,又避免了复杂的指针重连逻辑。swap 对于指针交换的是地址内容,对于基本类型交换的是值,这里我们交换的是 key 值。

性能对比

与有序数组的二分查找相比,BST 在插入和删除上更具优势(O(log N)),而数组需要移动元素(O(N))。但 BST 的劣势在于最坏情况下可能退化为链表,导致查询效率降至 O(N)。因此,在实际工程中常需配合平衡策略(如 AVL 树、红黑树)使用。

搜索模型

  1. Key 搜索:快速判断存在性。例如门禁系统验证车辆权限。
  2. Key-Value 搜索:通过键查找对应值。例如高铁实名制车票系统。

注意 key 一般是不允许重复的信息。如果是 k-v 模型,成员变量需增加 value,Insert 和 Erase 操作的形参也要相应调整。

实战演练

1. 二叉搜索树转双向链表

利用中序遍历的特性,将节点的 left 指向前驱,right 指向后继。遍历时维护一个 prev 引用即可。

易错点:最后返回的头结点通常是整棵树的最左侧节点,而非传入的根节点。且叶子节点也需要更新 prev->right。

void Inorder(TreeNode* cur, TreeNode*& prev) {
    if (!cur) return;
    Inorder(cur->left, prev);
    cur->left = prev;
    if (prev) prev->right = cur;
    prev = cur;
    Inorder(cur->right, prev);
}

2. 根据遍历序列构造二叉树

给定前序和中序遍历,可以唯一确定一棵二叉树。前序确定根,中序分割左右子树区间。后序与中序同理,只是根的位置不同。

关键点:递归时需要传递索引引用,确保全局索引状态同步更新。创建空间时记得用 new,且参数要带引用。

3. 非递归遍历

使用栈模拟递归过程。前序遍历在入栈时访问节点;中序遍历在出栈时访问节点;后序遍历较复杂,需记录上一个访问节点,判断是否满足'右子树为空'或'右子树已访问'的条件。

这些题目涵盖了树结构的核心操作,掌握它们对理解递归、栈以及指针操作至关重要。实际编码时,注意区分 while 和 if 的使用场景,避免死循环或漏判。

目录

  1. 概述
  2. 核心实现
  3. 性能对比
  4. 搜索模型
  5. 实战演练
  6. 1. 二叉搜索树转双向链表
  7. 2. 根据遍历序列构造二叉树
  8. 3. 非递归遍历
  • 免费图片AI生成工具免费生成了解详情
  • Magick API 一键接入全球大模型注册送1000万token查看
  • 免费图片视频在线生成30秒,将你的创意变成现实开始设计
  • X/Twitter免费视频下载器免登陆无限额度免费视频解析下载了解详情
  • 100+免费在线小游戏爽一把
极客日志微信公众号二维码

微信扫一扫,关注极客日志

微信公众号「极客日志V2」,在微信中扫描左侧二维码关注。展示文案:极客日志V2 zeeklog

更多推荐文章

查看全部
  • 网络安全基础与黑客技术入门指南
  • 前端常用流程图框架盘点:组态图、思维导图与拓扑图开发指南
  • MySQL 权限管理与 C/C++ 客户端开发实战
  • OpenAI 直播前瞻、AI Agent 行业地图与提示工程大赛经验分享
  • 网络安全入门与渗透测试学习路线指南
  • 使用 Continue 插件本地部署 AI 代码助手替代 Cursor 或 Copilot
  • VS Code 结合 Overleaf Workshop 插件实现本地 AI 辅助 LaTeX 写作
  • 动态规划入门:斐波那契模型与经典例题
  • 基于 Docling、Ollama、Phi-4 与 ExtractThinker 的企业级文档智能处理方案
  • 实测 Gemini Pro:谷歌多模态 AI 的实际应用能力
  • 利用 Ollama 在 VS Code 中私有化部署 AI 编程助手
  • Python 数据科学工具链入门:NumPy、Pandas、Matplotlib 快速上手
  • Python 在 CentOS 系统上的安装、配置与部署实战
  • 沙盒网络:利用云基础设施优化全球 UGC 游戏体验
  • 使用 BFS 实现拓扑排序
  • 基于 DeepSeek 的 AI 对话系统构建:Spring Boot + 前端实战指南
  • 数据结构:顺序表原理与实现
  • Stable Diffusion XL 1.0 灵感画廊镜像免配置部署与使用指南
  • Visual C++ 6.0 在 Windows 11 下的安装与兼容性配置指南
  • PyBind11 使用全解析:C++ 与 Python 高效绑定

相关免费在线工具

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online

  • Base64 字符串编码/解码

    将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online

  • Base64 文件转换器

    将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online

  • Markdown转HTML

    将 Markdown(GFM)转为 HTML 片段,浏览器内 marked 解析;与 HTML转Markdown 互为补充。 在线工具,Markdown转HTML在线工具,online

  • HTML转Markdown

    将 HTML 片段转为 GitHub Flavored Markdown,支持标题、列表、链接、代码块与表格等;浏览器内处理,可链接预填。 在线工具,HTML转Markdown在线工具,online