二叉搜索树:数据结构之美

news2024/9/26 3:25:14

目录

  1. 引言
  2. 基础知识
    • 定义
    • 性质
  3. 操作详解
    • 插入节点
    • 删除节点
    • 查找节点
    • 遍历
      • 前序遍历
      • 中序遍历
      • 后序遍历
  4. 高级主题
    • 平衡问题
    • AVL树简介
  5. 应用案例
  6. 总结

引言

二叉搜索树(Binary Search Tree, BST)是一种特殊的二叉树,它的每个节点具有以下性质:左子树上的所有节点的键值均小于它的根节点的键值;右子树上所有节点的键值均大于它的根节点的键值。这种结构使得二叉搜索树成为了高效查找、插入和删除数据的理想选择。

基础知识

定义

二叉搜索树是一种二叉树,其中每个节点包含一个键值、一个指向左子树的引用以及一个指向右子树的引用。左子树中的所有节点的键值小于该节点的键值,而右子树中的所有节点的键值大于该节点的键值。

性质

  • 唯一性:给定一组键值,存在唯一的二叉搜索树。
  • 中序遍历:对二叉搜索树进行中序遍历时,返回的键值序列是递增排序的。
  • 查找效率:在理想情况下,查找、插入和删除操作的时间复杂度为O(log n),其中n是树中节点的数量。

操作详解

插入节点

插入操作涉及比较新键值与树中节点的键值,并沿着树向下移动,直到找到合适的位置。

TreeNode* BinarySearchTree::_insert(TreeNode* node, int key) {
    if (node == nullptr) {
        return new TreeNode(key);
    }

    if (key < node->key) {
        node->left = _insert(node->left, key);
    } else if (key > node->key) {
        node->right = _insert(node->right, key);
    }

    return node;
}

void BinarySearchTree::insert(int key) {
    root = _insert(root, key);
}

删除节点

删除操作分为三种情况:

  1. 节点没有子节点(叶节点)。
  2. 节点有一个子节点。
  3. 节点有两个子节点。
TreeNode* BinarySearchTree::_minValueNode(TreeNode* node) {
    TreeNode* current = node;
    while (current && current->left != nullptr) {
        current = current->left;
    }
    return current;
}

TreeNode* BinarySearchTree::_remove(TreeNode* node, int key) {
    if (node == nullptr) {
        return node;
    }

    if (key < node->key) {
        node->left = _remove(node->left, key);
    } else if (key > node->key) {
        node->right = _remove(node->right, key);
    } else {
        if (node->left == nullptr) {
            TreeNode* temp = node->right;
            delete node;
            return temp;
        } else if (node->right == nullptr) {
            TreeNode* temp = node->left;
            delete node;
            return temp;
        }

        TreeNode* temp = _minValueNode(node->right);
        node->key = temp->key;
        node->right = _remove(node->right, temp->key);
    }

    return node;
}

void BinarySearchTree::remove(int key) {
    root = _remove(root, key);
}

查找节点

查找操作用于确定树中是否存在某个键值。

bool BinarySearchTree::_find(TreeNode* node, int key) const {
    if (node == nullptr) {
        return false;
    }

    if (key == node->key) {
        return true;
    } else if (key < node->key) {
        return _find(node->left, key);
    } else {
        return _find(node->right, key);
    }
}

bool BinarySearchTree::find(int key) const {
    return _find(root, key);
}

遍历

前序遍历

前序遍历的顺序是根节点、左子树、右子树。

void BinarySearchTree::_preorderTraversal(TreeNode* node) const {
    if (node != nullptr) {
        std::cout << node->key << " ";
        _preorderTraversal(node->left);
        _preorderTraversal(node->right);
    }
}

void BinarySearchTree::preorderTraversal() const {
    _preorderTraversal(root);
}
中序遍历

中序遍历的顺序是左子树、根节点、右子树。对于二叉搜索树,这将返回一个升序的键值序列。

void BinarySearchTree::_inorderTraversal(TreeNode* node) const {
    if (node != nullptr) {
        _inorderTraversal(node->left);
        std::cout << node->key << " ";
        _inorderTraversal(node->right);
    }
}

void BinarySearchTree::inorderTraversal() const {
    _inorderTraversal(root);
}
后序遍历

后序遍历的顺序是左子树、右子树、根节点。

void BinarySearchTree::_postorderTraversal(TreeNode* node) const {
    if (node != nullptr) {
        _postorderTraversal(node->left);
        _postorderTraversal(node->right);
        std::cout << node->key << " ";
    }
}

void BinarySearchTree::postorderTraversal() const {
    _postorderTraversal(root);
}

高级主题

平衡问题

二叉搜索树虽然提供了快速的查找、插入和删除操作,但其性能高度依赖于树的高度。最坏的情况下,树可能变得非常不平衡,导致时间复杂度退化至O(n)。为了保持树的平衡,一些变种被提出,例如AVL树和红黑树。

AVL树简介

AVL树是一种自平衡二叉搜索树,它保证任何节点的两个子树的高度差不超过1。AVL树通过旋转操作来维持平衡,在插入或删除节点后可能需要进行旋转以恢复平衡。

插入操作

当插入一个节点后,AVL树可能会变得不平衡。需要通过以下四种类型的旋转来恢复平衡:

  • 单旋转:右旋或左旋。
  • 双旋转:右旋+左旋或左旋+右旋。
删除操作

删除节点后也需要考虑树的平衡性,可能的操作与插入类似,包括单旋转和双旋转。


应用案例

二叉搜索树在多种场景下都有广泛的应用:

  1. 数据库索引:许多数据库系统使用类似二叉搜索树的数据结构来加速查询过程。
  2. 符号表:编程语言解释器和编译器使用二叉搜索树来管理符号表。
  3. 文件系统:某些文件系统使用二叉搜索树来管理文件和目录的结构。
  4. 优先队列:二叉搜索树可以用来实现优先队列,特别是当使用自平衡变种如AVL树时。

总结

本文介绍了二叉搜索树的基本概念、主要操作以及一些高级主题。通过学习这些内容,您不仅能够理解二叉搜索树的工作原理,还能够掌握如何有效地使用它们来解决实际问题。此外,本文还探讨了自平衡二叉搜索树的概念,这是处理大规模数据集时的一个重要工具。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2077506.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Python数据采集与网络爬虫技术实训室解决方案

在大数据与人工智能时代&#xff0c;数据采集与分析已成为企业决策、市场洞察、产品创新等领域不可或缺的一环。而Python&#xff0c;作为一门高效、易学的编程语言&#xff0c;凭借其强大的库支持和广泛的应用场景&#xff0c;在数据采集与网络爬虫领域展现出了非凡的潜力。唯…

Mysql重要参数

1、是否开启慢SQL日志 show VARIABLES like slow_query_log%; 2、慢SQL日志保存位置 show VARIABLES like slow_query_log_file%; 3、慢SQL的阈值&#xff0c;超过则是慢SQL&#xff0c;单位秒&#xff0c;默认10s show VARIABLES like long_query_time%;

小阿轩yx-Kubernetes存储入门

小阿轩yx-Kubernetes存储入门 前言 数据是一个企业的发展核心&#xff0c;它涉及到数据存储和数据交换的内容。在生产环境中尤为重要的一部分在 Kubernetes 中另一个重要的概念就是数据持久化 Volume。 Volume 的概念 对多数项目而言 数据文件的存储是非常常见的 在 Kube…

计算机的错误计算(七十四 )

摘要 回复网友的疑问&#xff1a;用错数解释计算机的错误计算&#xff08;六十四&#xff09;中的错误计算原因。 计算机的错误计算&#xff08;六十四&#xff09;到&#xff08;六十九&#xff09;&#xff0c;以及&#xff08;七十一&#xff09;与&#xff08;七十三&…

攻防世界 1000次点击

做题笔记。 下载解压 查壳。 32位ida打开。 查找字符串。 winmain函数写的&#xff0c;程序运行如下&#xff1a; 一开始思路是想着分析找到关键代码然后去od进行调试。 后来&#xff0c;额&#xff0c;不想看代码了。吐了。 尝试去字符串搜索flag样式&#xff0c;确实一发现…

高效恢复,无忧存储:2024年数据恢复工具大搜罗

不知道你是否了解过电子存储设备&#xff0c;我们的设备往往都存储在一个小小的芯片里&#xff0c;它为我们提供了数据携带的便捷性&#xff0c;当然也为我们带来了数据意外丢失的风险。为了我们的数据安全&#xff0c;我们来探讨一下有什么数据恢复工具能为我们的资料保驾护航…

Ruo-Yi 前后端分离如何不使用注解@DataSource的方式而是使用Mybatis插件技术实现多数据源的切换【可以根据配置文件进行开启/关闭】

Ruo-Yi 前后端分离如何不使用注解DataSource的方式而是使用Mybatis插件技术实现多数据源的切换【可以根据配置文件进行开启/关闭】 1、首先 配置文件&#xff1a; # 数据源配置 spring:datasource:type: com.alibaba.druid.pool.DruidDataSourcedriverClassName: com.mysql.c…

ZooKeeper--基于Kubernetes部署ZooKeeper

ZooKeeper 服务 服务类型: 无头服务&#xff08;clusterIP: None&#xff09;&#xff0c;这是 StatefulSet&#xff08;有状态集&#xff09;必需的配置。 端口: 2181 (客户端): 用于客户端连接。 2888 (跟随者): 用于 ZooKeeper 服务器之间的连接。 3888 (领导者): 用于领导者…

邮政快递批量查询解决方案:提升业务运营效率

邮政快递批量查询&#xff1a;固乔快递查询助手的高效体验 在电商行业日益繁荣的今天&#xff0c;快递物流成为了连接商家与消费者的关键纽带。而对于需要处理大量订单的电商企业或个人而言&#xff0c;如何高效、准确地查询和跟踪快递物流信息显得尤为重要。幸运的是&#xf…

linux 云主机下载压缩包安装配置 maven 实录(华为云 EulerOS)

本想通过 yum install maven 直接安装的, 方便省事, 但报错说没找到, 于是只能手动安装了, 把整个过程记录了一下, 包括下载, 解压, 配置及验证的全过程, 并对用到的命令及参数作了详细说明, 需要的同学可以参考. maven 官网找到下载链接 首先要去到 maven 的官网, https://m…

OpenCV+Python自动填涂机读卡

接上一篇OpenCVPython识别机读卡-CSDN博客&#xff0c;既然可以识别机读卡填涂答案了&#xff0c;将标准答案绘制到机读卡上也就简单了。 工作原理 1.答题区域为整张图片最大轮廓&#xff0c;先找出答题区域。 2.答题区域分为6行&#xff0c;每行4组&#xff0c;第6行只有1组…

【Java设计模式】抽象文档模式:以灵活性简化数据处理

文章目录 抽象文档设计模式的意图抽象文档模式的详细解释及实际示例Java中抽象文档模式的编程示例抽象文档模式类图Java中何时使用抽象文档模式抽象文档模式的优点和权衡源码下载参考和致谢 抽象文档设计模式的意图 Java中的抽象文档设计模式是一种关键的结构设计模式&#xf…

【mysql集群之组复制】

目录 一、 mysql高可用之组复制 (MGR)组复制单主和多主模式实现mysql的组复制 二、 mysql-router&#xff08;mysql路由&#xff09;实现负载均衡 一、 mysql高可用之组复制 (MGR) MySQL Group Replication(简称 MGR )是 MySQL 官方于 2016 年 12 月推出的一个全新的高可用与高…

OpenHarmony南向开发:SmartPerf-Device使用说明

简介 SmartPerf 端是一款基于 OpenHarmony 系统开发的性能功耗测试工具&#xff0c;操作简单易用&#xff0c;可提供包括性能、功耗的关键 KPI 指标&#xff0c;给出具体指标的测试值&#xff0c;包括采集设备的 FPS、CPU、GPU、Ftrace 等指标数据&#xff1b; 目前 SmartPer…

uniapp之app版本更新,整体更新和热更新

目录 需求&#xff1a; 版本更新有两种更新模式&#xff1a; 实现&#xff1a; 前提&#xff1a; 热更新&#xff1a; 打包wgt包&#xff1a;菜单->发行->原生App-制作移动App资源升级包 代码逻辑: 整体更新&#xff1a; 实际项目开发&#xff1a; 需求&#xf…

Linux网络编程——C/C++Web服务器(二):IO多路复用select/poll/epoll实现服务器监听多客户端事件

环境配置&#xff1a;windows电脑用户可以安装WSL配置Linux环境&#xff0c;并且安装vscode及wsl的插件通过vscode连接本机电脑的Linux。 前置内容&#xff1a; Linux网络编程——C/CWeb服务器&#xff08;一&#xff09;&#xff1a;不断创建新线程处理多客户端连接和通信-C…

代码随想录算法训练营第二十七天(贪心 一)

硬拖拖到现在才写完。。。 关于贪心: 文章链接: 代码随想录 文章摘要: 贪心的本质是选择每一阶段的局部最优&#xff0c;从而达到全局最优。 贪心算法并没有固定的套路。 和其他算法不同&#xff0c;贪心没有能看出局部最优是否能推出整体最优的通法。 用来验证可不可以…

软件渗透测试必要性简析,第三方软件测试机构如何进行渗透测试?

在信息技术迅速发展的今天&#xff0c;软件渗透测试逐渐成为了确保信息安全的重要环节。软件渗透测试指的是对系统或应用程序进行模拟攻击&#xff0c;以发现其潜在的安全风险与脆弱性。不同于传统的安全审计&#xff0c;渗透测试更注重实际攻击过程和攻击者的视角&#xff0c;…

IO进程线程8月26ri

1&#xff0c;思维导图 2&#xff0c;用两个进程分别复制文件的上下两部分到另一个文件 #include<myhead.h> int main(int argc, const char *argv[]) {int fpopen("./1.txt",O_RDONLY);if(fp-1){perror("open");return -1;}int countlseek(fp,0,SE…

如何在 mind+ 中编写 python 程序

打开Mind&#xff0c;点击窗口右上角的【Python模式】按钮&#xff0c;由实时模式切换到Python模式。 将默认的循环执行模块拖动到左边的模块区删除。 点击【变量】&#xff0c;将【打印【Hello World】】模块拼接到【Python主程序开始】下方。 将【获取输入&#xff0c;提示语…