数据结构与算法-二叉排序树

引言

        在计算机科学中,数据结构和算法是构建高效程序的核心要素。其中,二叉排序树(Binary Search Tree, BST)作为一种基于二叉树的特殊数据结构,因其在搜索、插入和删除操作上的优秀性能而被广泛应用。本文将详细解析二叉排序树的定义、性质、操作方法以及实际应用场景。

一、什么是二叉排序树?

二叉排序树 是一种特殊的二叉树,它满足以下性质:

  1. 每个节点包含一个键(key),这个键用于确定节点在树中的位置。
  2. 左子树中所有节点的键值均小于其父节点的键值。
  3. 右子树中所有节点的键值均大于其父节点的键值。
  4. 左右子树也必须各自为二叉排序树。

二、二叉排序树的操作方法

  1. 查找操作:从根节点开始,如果目标键等于当前节点的键,则查找成功;若目标键小于当前节点键值,则在左子树中递归查找;若目标键大于当前节点键值,则在右子树中递归查找。

  2. 插入操作:同样从根节点开始,如果树为空则直接创建新节点作为根节点;否则按照查找过程找到合适的位置插入新的节点,保持二叉排序树的性质不变。

  3. 删除操作:删除节点的过程相对复杂,需要考虑三种情况:要删除的节点无子节点、仅有一个子节点或有两个子节点。在保证二叉排序树特性的前提下,调整树的结构以完成删除。

三、二叉排序树的特性与优缺点

  • 优点

    • 查找、插入和删除操作的时间复杂度在理想情况下均可达到O(log n),其中n代表树中节点的数量,这是因为每次比较都能排除一半的数据。
    • 能够自动保持数据有序,便于进行范围查询。
  • 缺点

    • 当数据分布不均匀时,二叉排序树可能退化成链表形态,导致查找效率降低到O(n)。
    • 插入和删除操作可能导致树频繁地不平衡,从而影响整体性能。

四、改进型二叉排序树

为了克服二叉排序树在最坏情况下的性能问题,出现了许多改进型的二叉排序树,例如:

  • 自平衡二叉排序树(如AVL树、红黑树等):通过引入额外的平衡条件和旋转操作来确保树的高度始终保持在对数级别,从而维持高效的查找、插入和删除性能。

五、二叉排序树的实际应用

二叉排序树广泛应用于软件开发和计算机科学领域,包括但不限于:

  • 数据库索引:部分数据库系统利用自平衡二叉排序树实现索引结构,提高数据查询速度。
  • 文件系统:某些文件系统使用类似二叉排序树的数据结构组织目录结构,快速定位文件。
  • 内存管理:操作系统内核在分配和回收内存时,可能会用到具有排序性质的二叉树结构。

六、二叉排序树的代码实践  

1.节点类

//节点
class Node {int value;Node lift;Node right;public Node(int value) {this.value = value;}@Overridepublic String toString() {return "Node{" +"value=" + value +'}';}//    二叉排序树添加节点方法public void add(Node node) {if (node == null) {return;}
//        判断传入的节点值与当前节点大小的关系if (node.value < this.value) {   //小于该节点
//            如果当前节点左子节点为空直接添加在其左子节点if (this.lift == null) {this.lift = node;} else {
//                递归向左this.lift.add(node);}} else {    //大于该节点
//            如果当前节点右子节点为空直接添加在其右子节点if (this.right == null) {this.right = node;} else {
//                递归向右this.right.add(node);}}}//    中序遍历public void infixOrder() {if (this.lift != null) {this.lift.infixOrder();}System.out.println(this);if (this.right != null) {this.right.infixOrder();}}//    中序查找删除的节点public Node search(int value) {if (this.value == value) {return this;} else if (value < this.value) {if (this.lift == null) {return null;}return this.lift.search(value);} else {if (this.right == null) {return null;}return this.right.search(value);}}//    查找删除节点的父节点public Node searchParent(int value) {if ((this.lift != null && this.lift.value == value) ||(this.right != null && this.right.value == value)) {return this;    //该节点就是删除节点的父节点} else {if (value < this.value && this.lift != null) {   //向左递归return this.lift.searchParent(value);} else if (value >= this.value && this.right != null) {  //向右递归return this.right.searchParent(value);}}return null;  //没有父节点}
}

2.二叉树类添加节点 

class BinarySortTree {private Node root;//    添加节点public void add(Node node) {if (root == null) {root = node;} else {root.add(node);}}//    中序遍历public void infixOrder() {if (root == null) {return;}root.infixOrder();}
}

3.删除节点 

    //    查找删除节点public Node search(int value) {if (root == null) {return null;}return root.search(value);}//    查找删除节点的父节点public Node searchParent(int value) {if (root == null) {return null;}return root.searchParent(value);}//    返回以node为根节点的二插排序树的最小节点值
//    删除node为根节点的二叉排序树的最小节点/*** @param node 传入节点 当做二叉树的根节点* @return 以node为根节点二插排序树最小节点值*/public int delRightTreeMin(Node node) {Node target = node;
//        循环找左节点就会找到最小值while (target.lift != null) {target = target.lift;}deleteNode(target.value);return target.value;}/*** @param node 传入节点 当做二叉树的根节点* @return 以node为根节点二插排序树最大节点值*/public int delLiftTreeMax(Node node) {Node target = node;while (target.right != null) {target = target.right;}deleteNode(target.value);return target.value;}//    删除节点public void deleteNode(int value) {if (root == null) {return;} else {
//            先找到要删除的节点Node targetNode = search(value);if (targetNode == null) {return;}
//            如果发现当前二插排序树没有左子节点且没有右子节点就直接删除该节点if (root.lift == null && root.right == null) {root = null;return;}
//            找到要删除节点的父节点Node parentNode = searchParent(value);
//            如果删除的节点为叶子节点if (targetNode.lift == null && targetNode.right == null) {
//                判断targetNode是parentNode的左子节点还是右子节点if (parentNode.lift != null && parentNode.lift.value == value) {parentNode.lift = null;} else if (parentNode.right != null && parentNode.right.value == value) {parentNode.right = null;}
//                非叶子节点} else if (targetNode.lift != null && targetNode.right != null) {    //有两颗子树
//                int minValue = delRightTreeMin(targetNode.right);
//                targetNode.value = minValue;
//                  这里可以有两种方案int maxValue = delLiftTreeMax(targetNode.lift);targetNode.value = maxValue;} else {  //有一颗子树的节点if (targetNode.lift != null) {  //要删除的是左子节点if (parentNode != null) {
//                    targetNode 是 parentNode 的左子节点if (parentNode.lift.value == value) {parentNode.lift = targetNode.lift;} else {root = targetNode.lift;}} else {parentNode.right = targetNode.lift;}} else {  //要删除的是右子节点if (parentNode != null) {if (parentNode.lift.value == value) {parentNode.lift = targetNode.right;} else {root = targetNode.right;}} else {parentNode.right = targetNode.right;}}}}}

七、总结        

        二叉排序树作为一种基础且实用的数据结构,在处理动态集合、提供快速访问、维护数据有序等方面展现出显著优势。尽管在极端情况下存在性能下降的问题,但通过对二叉排序树进行优化和改进,可以使其成为现代计算机科学诸多领域的基石之一。熟练掌握并灵活运用二叉排序树原理及其实现方法,对于提升编程能力和解决实际工程问题至关重要。

 

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

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

相关文章

网络编程(3/6)

使用C语言完成数据库的增删改 #include<myhead.h> int do_add(sqlite3 *ppDb) {int numb;char name[50];int salary;printf("请输入员工信息&#xff1a;工号、姓名、薪水\n");scanf("%d %s %d",&numb,name,&salary);char sql[128];char *e…

Nginx七层的负载均衡使用keepalived实现高可用

目录 一、环境准备 二、两台nginx服务器作为代理服务器,配置nginx的负载均衡 三、Keepalived实现调度器 Proxy-master 与 Proxy-slave机器同时操作安装 备份配置文件 编辑主Proxy-master的配置文件 编辑从 Proxy-slaver的配置文件 四、 启动KeepAlived&#xff08;主备…

PokéLLMon 源码解析(一)

.\PokeLLMon\poke_env\concurrency.py # 导入必要的模块 import asyncio import atexit import sys from logging import CRITICAL, disable from threading import Thread from typing import Any, List# 在新线程中运行事件循环 def __run_loop(loop: asyncio.AbstractEvent…

CleanMyMac X4.15中文完整免费版下载

CleanMyMac X是一款功能全面的Mac管理软件&#xff0c;它能帮助用户清理无用的文件&#xff0c;监控系统健康&#xff0c;管理启动项&#xff0c;甚至还能移除恶意软件&#xff0c;确保你的Mac保持最佳状态。其直观的界面设计使得新手用户也能轻松上手&#xff0c;一键扫描和清…

【算法】一类支持向量机OC-SVM

【算法】一类支持向量机OC-SVM 前言一类支持向量机OC-SVM 概念介绍示例编写数据集创建实现一类支持向量机OC-SVM完整的示例输出 前言 由于之前毕设期间主要的工具就是支持向量机&#xff0c;从基础的回归和分类到后来的优化&#xff0c;在接触到支持向量机还有一类支持向量机的…

脚手架cli快速创建Vue2/Vue3项目

前言&#xff1a; 本文的nodejs版本是14.21.3 第一步 进入cmd窗口 1、全局安装webpack npm install webpack-g&#xff0c; npm install webpack-g 第二步 2、全局安装vue脚手架 npm install -g vue/cli 第三步 3、初始化vue项目 &#xff08;vue脚手架使用webpack模…

宝妈做什么兼职副业好?适合她们的有哪些?执行力才是关键

现在的宝妈&#xff0c;生完孩子以后&#xff0c;尤其是宝宝上幼儿园之前&#xff0c;为了照顾宝宝&#xff0c;不能去外面上班&#xff0c;所以很多妈妈都为孩子做出了很大的牺牲&#xff0c;但同时又要承担着家庭经济的压力&#xff0c;尤其是现在注重个性独立的时代&#xf…

Spring整合Flyway使用笔记

引入依赖 <dependency><groupId>org.flywaydb</groupId><artifactId>flyway-core</artifactId><version>8.0.5</version> </dependency>配置application.yml --- # flay config spring:flyway:# 启用或禁用 flywayenabled: tr…

基于微信小程序的电子商城购物平台的设计与实现(论文+源码)_kaic

摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;电子商城购物平台小程序被用户普遍使用&#xff0c;为方便…

图及图的存储

目录 1.图的相关概念 2.图的存储 2.1.直接存法 1.查询是否存在某条边 2.遍历一个点的所有出边 3..遍历整个图 应用 2.2.邻接矩阵 1.查询是否存在某条边 2.遍历一个点的所有出边 3..遍历整个图 应用 2.3.邻接表 1.查询是否存在某条边 2.遍历一个点的所有出边 3..遍…

RabbitMQ应用场景

1、异步处理 假设想象一下我们做一个商城项目&#xff0c;在用户支付模块中&#xff0c;可能会涉及到其它业务&#xff0c;比如&#xff1a;积分折扣、消费券、短信验证等功能。我们传统的执行步骤是逐步执行&#xff0c;也就是说当用户点击支付 ----> 积分折扣 ----> 消…

Project_Euler-10 题解

Project_Euler-10 题解 题目 思路 没有思路&#xff0c;一个线性筛秒了,只不过最近没发博客有点手生哈哈哈哈哈。 代码 /*************************************************************************> Author: Royi > Mail: royi990001gmail.com > From: > Lan…

2014-2023年上市银行华证ESG评级数据/银行ESG评级数据

2014-2023年上市银行华证ESG评级数据/银行ESG评级数据 1、时间&#xff1a;2014-2023年 2、指标&#xff1a;证券代码、证券简称、华证ESG评级 3、来源&#xff1a;原始数据整理自wind 4、范围&#xff1a;42家银行&#xff1a; 苏农银行、中信银行、贵阳银行、中国银行、…

力扣---接雨水---单调队列+动态规划+双指针

题目&#xff1a; 单调队列思想&#xff1a; 没有思路的小伙伴可以先把这个想清楚哦&#xff1a;力扣hot10---大根堆双端队列-CSDN博客 从上面的图就可以发现&#xff0c;如果柱子呈递减序列&#xff0c;那么不会接到雨水&#xff0c;只要有一个小凸起柱子&#xff0c;那么这个…

关于逆变器软起电压环和电流环工作模态分析

锁相 目前有两种主流方法&#xff1a;一是DDSRF(双同步参考坐标系软件锁相环)、二是SOGI(基于二阶广义积分器软件锁相环)&#xff0c;网上资料很多&#xff0c;这里就不做过多介绍。 逆变电压软起 逆变电压软起主要是为了吸合继电器瞬间不会产生过大的冲击电流&#xff0c;防…

智慧城市的前景:数字孪生技术在智慧城市中的应用前景

目录 一、引言 二、数字孪生技术及其在智慧城市中的应用概述 三、数字孪生技术在智慧城市中的应用前景 1、城市规划与仿真模拟 2、智能交通与出行服务 3、智慧环保与可持续发展 4、智慧公共服务与社会治理 5、智慧能源与绿色建筑 四、数字孪生技术在智慧城市中的挑战与…

Tengine 的HTTP3,如何适配四层负载的udp健康检查?

HTTP3为什么要适配udp健康检查&#xff1f; 不同于HTTP2和HTTP1.1以及之前的HTTP协议&#xff0c;HTTP3最大的不同就是其传输层协议由TCP改成了基于UDP实现的QUIC协议。QUIC 协议实现在用户态&#xff0c;建立在内核态的 UDP 的基础之上&#xff0c;集成了 TCP 的可靠传输特性…

SpringCloud(21)之SpringCloud Alibaba Nacos实战应用

一、Nacos安装 1.1 Nacos概述 Nacos是Alibaba微服务生态组件中的重要组件之一&#xff0c;主要用它实现应用的动态服务发现、配置管理、 服务管理。Nacos discovery alibaba/spring-cloud-alibaba Wiki GitHub Nacos 致力于帮助您发现、配置和管理微服务。Nacos 提供了一组简…

Oracle.xs.dll‘ for module DBD::Oracle: load_file:找不到指定的模块

安装Ora2pg时,碰到 异常现象 D:\ProgramFiles\ora2pg>ora2pg -t show_report --estimate_cost -c ora2pg_conf.dist install_driver(Oracle) failed: Cant load D:/ProgramFiles/strawberry/perl/site/lib/auto/DBD/Oracle/Oracle.xs.dll for module DBD::Oracle: load_fil…

鸿蒙开发-UI-动画-组件内转场动画

鸿蒙开发-UI-组件3 鸿蒙开发-UI-气泡/菜单 鸿蒙开发-UI-页面路由 鸿蒙开发-UI-组件导航-Navigation 鸿蒙开发-UI-组件导航-Tabs 鸿蒙开发-UI-图形-图片 鸿蒙开发-UI-图形-绘制几何图形 鸿蒙开发-UI-图形-绘制自定义图形 鸿蒙开发-UI-图形-页面内动画 文章目录 前言 一、基本概…