二叉搜索树

1.基础概念介绍

二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:

1.若它的左子树不为空,则左子树上所有节点的值都小于根节点的值

2.若它的右子树不为空,则右子树上所有节点的值都大于根节点的值

3.它的左右子树也分别为二叉搜索树
在这里插入图片描述

如图所示就是一颗二叉树,其先从根开始找起(一般走中序遍历),因为节点左边的值总比节点小,右边的值总比节点打,所以遍历完一遍还没有找到的话,说明这个数字不存在。

2.二叉搜索树的基本功能实现

2.1单个节点类
tmeplate<class K>
strust BSTreeNode
{
    BSTreeNode* _left;
    BSTreeNode* _right;
    K _key;
    
    BSTreeNode(const K& key)
        :_left(nullptr)
        ,_rihgt(nullptr)
        ,_ket(key)
        {}     
};
2.2BS树主体
tmepalte<class k>
class BSTree
{
    typedef BSTreeNode<K> Node;  //其实还是那老一套,这里的封装就相对简单多了
    BSTree()
        :_root(nullptr)
        {}
    
    private:
    Node* _root
};
2.3插入
bool insert(const k& key)
{
    if(_root == nullptr)
    {
        Node* cur = new Node(kety);
        return true;
    }
  Node* cur = _root;
  Node* parent = nullptr;
  while(cur)
  {
      if(cur->_key < key)
      {
          parent = cur;
          cur = cur->_right;
    
      }
      else if
      {
          parent = cur;
          cur = cur->_left;
      }
      else
      {
          return false;
      }
  }
    cur = new Node(key);
    if(parent->_key > key)
    {
       parent->_left = parent;
    }
    else
    {
       parent->_right = parent;
    }
    return true;
}
2.4删除
bool Erase(const k& key)
{
    Node* parent = nullptr;
    Node* cur = _root;
    while(cur)
    {
        if(cur->_key < key)
        {
            parent = cur;
            cur = cur->left;
        }
        else if(cur->_key > key)
        {
            parent = cur;
            cur = cur->right;
        }
        else
        {
            //找到准备开始删除
          if(cur->_left == nullptr)
          {
             if(parent == nullptr)
             {
                 _root->cur->_right;
             }
              else 
              {
                  if(parent->_left == cur)
                  parent->_left = cur->_right;
                  else
                  parent->_right = cur->_right;
              }
              delete cur;
          }
            
            if(cur->_right == nullptr)
          {
             if(parent == nullptr)
             {
                 _root->cur->_left;
             }
              else 
              {
                  if(parent->_left == cur)
                  parent->_left = cur->_left;
                  else
                  parent->_right = cur->_left;
              }
              delete cur;
          }
            
            if(cur->_right != nullptr && cur->_left != nullptr)
            {
                Node* minParent = cur;
                Node* min = cur->right;
                while(min->left)
                {
                    minParent = min;
                    min = min->left;
                }
                cur->_key = min->_key;
                if (minParent->_left == min)
					minParent->_left = min->_right;
				else
					minParent->_right = min->_right;

				delete min;
            }
            return true;
        }
    }
    return false;
}

在这里插入图片描述
在这里插入图片描述

这棵树的重点其实就是删除功能,可以看到上图我们一共会出现这三种情况(当然这里的图画的不完全,但是大致我们可以分为3类):

我们先来讲解一二两类:

如一二两图所示当出现这种情况时候我们优先考虑:

1.此时要删除的节点是否为根节点(根节点要是变化了需要更改)

2.删除后我们将其左结点或者右结点和其父结点相互连接,此时应该去区分是父结点的右和我相互关联还是左。

而碰到图三的情况我将讲解下这里用到的代码细节和思路:

1.其实我们遇到图三这种情况,处理方法无非是找其左端的最大值,或者右端的最小值,而这里我们采用的是寻找右端最小数值的方法(可以画图比较一下这两方法我为什么选择后者)

2.其次这里不需要考虑删除的是否为根结点的问题(因为我实际操作是不可能去删根结点的)

3.在我使用第二种方法后,其依旧需要判断一下父结点是连哪个方向(具体参考下面这张图)

在这里插入图片描述

2.5查找
bool Find(const k& key)
{
    Node*cur = _root;
    while(cur)
    {
        if(cur->_key > key)
        {
            cur = cur->left;
        }
       else if(cur->_key<key)
       {
           cur = cur->right;
       }
        else
        {
            return true;
        }     
    }
    return false;
}

基本功能到这里已经实现完成了,当然这里会有一个递归的版本,但是正常情况下我们不会去使用递归的这种方法去实现,当递归深度足够大时栈容易溢出。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

设置Typora图床(Github)

PicGo&#xff0c;Github&#xff0c;Typora Nodejs下载&#xff1a; Node.js PicGo下载&#xff1a; GitHub - Molunerfinn/PicGo: A simple & beautiful tool for pictures uploading built by vue-cli-electron-builder 选择downloads或release. 然后进行安装。 Gith…

经典PID控制算法原理以及优化思路

文章目录0、概念1、理解2、实现3、优化4、引用0、概念 PID算法是工业应用中最广泛算法之一&#xff0c;在闭环系统的控制中&#xff0c;可自动对控制系统进行准确且迅速的校正。PID控制&#xff0c;即Proportional – Integral(I) – Derivative(D) Control, 实际上是三种反馈…

Transformer到底为何这么牛

从注意力机制&#xff08;attention&#xff09;开始&#xff0c;近两年提及最多的就是Transformer了&#xff0c;那么Transformer到底是什么机制&#xff0c;凭啥这么牛&#xff1f;各个领域都能用&#xff1f;一文带你揭开Transformer的神秘面纱。 目录 1.深度学习&#xff0…

STM32外设-DMA

1. 简介 DMA(Direct Memory Access)—直接存储器存取&#xff0c;是单片机的一个外设&#xff0c;它的主要功能是用来搬数据&#xff0c;但是不需要占用 CPU&#xff0c;即在传输数据的时候&#xff0c; CPU 可以干其他的事情&#xff0c;好像是多线程一样。数据传输支持从外设…

初时STM32单片机

目录 一、单片机基本认知 二、STM系列单片机命名规则 三、标准库与HAL库区别 四、通用输入输出端口GPIO 五、推挽输出与开漏输出 六、复位和时钟控制&#xff08;RCC&#xff09; 七、时钟控制 八、中断和事件 九、定时器介绍 一、单片机基本认知 单片机和PC电脑相比…

【python进阶】你真的懂元组吗?不仅是“不可变的列表”

&#x1f4da;引言 &#x1f64b;‍♂️作者简介&#xff1a;生鱼同学&#xff0c;大数据科学与技术专业硕士在读&#x1f468;‍&#x1f393;&#xff0c;曾获得华为杯数学建模国家二等奖&#x1f3c6;&#xff0c;MathorCup 数学建模竞赛国家二等奖&#x1f3c5;&#xff0c…

图形视图框架 事件处理(item)

在图形界面框架中的事件都是先由视图进行接收&#xff0c;然后传递给场景&#xff0c;再由场景传递给图形项。通过键盘处理的话&#xff0c;需要设置焦点&#xff0c;在QGraphicsScene中使用setFoucesItem&#xff08;&#xff09;函数可以设置焦点&#xff0c;或者图形项使用s…

【二】一起算法---队列:STL queue、手写循环队列、双端队列和单调队列、优先队列

纸上得来终觉浅&#xff0c;绝知此事要躬行。大家好&#xff01;我是霜淮子&#xff0c;欢迎订阅我的专栏《算法系列》。 学习经典算法和经典代码&#xff0c;建立算法思维&#xff1b;大量编码让代码成为我们大脑的一部分。 ⭐️已更系列 1、基础数据结构 1.1、链表➡传送门 1…

【文心一言】什么是文心一言,如何获得内测和使用方法。

文心一言什么是文心一言怎么获得内测资格接下来就给大家展示一下文学创作商业文案创作数理逻辑推算中文理解多模态生成用python写一个九九乘法表写古诗前言&#xff1a; &#x1f3e0;个人主页&#xff1a;以山河作礼。 &#x1f4dd;​&#x1f4dd;:本文章是帮助大家了解文心…

24. linux系统基础

两个进程间想通讯&#xff0c;必须要通过内核&#xff0c;今天讲的信号其实本质也是讲进程间通讯的意思&#xff0c;那么你为什么可以在shell环境下&#xff0c;可以和一个进程发kill-9啊&#xff1f; shell是不是相当于一个进程&#xff1f;你自己运行的那个进程是不是也相当于…

HTTPS 加密协议

✏️作者&#xff1a;银河罐头 &#x1f4cb;系列专栏&#xff1a;JavaEE &#x1f332;“种一棵树最好的时间是十年前&#xff0c;其次是现在” 目录HTTPS"加密" 是什么HTTPS 的工作过程引入证书HTTPS http 安全层 (SSL) SSL 用来加密的协议&#xff0c;也叫 TLS …

GPT-4 API 接口调用及价格分析

GPT-4 API 接口调用及价格分析 15日凌晨&#xff0c;OpenAI发布了万众期待的GPT-4&#xff01;新模型支持多模态&#xff0c;具备强大的识图能力&#xff0c;并且推理能力和回答准确性显著提高。在各种专业和学术基准测试上的表现都媲美甚至超过人类。难怪OpenAI CEO Sam Altm…

HiveSql一天一个小技巧:利用array_contains()函数进行容器存在性计数问题分析

0 需求描述文章被引用关系数据表如下&#xff1a;idoid10203141526073其中id表示文章id,oid引用的文章&#xff0c;当oid为0时表示当前文章为原创文章&#xff0c;求原创文章被引用的次数。注意本题不能用关联的形式求解1 需求分析1.1 数据源准备with data as( select 1 as id,…

Springboot源代码总结

前言 编写微服务,巩固知识 文章目录 前言springboot原理springboot启动流程SpringBoot自动配置底层源码解析自动配置到底配了什么?自动配置类条件注解Starter机制@ConditionalOnMissingBeanSpringBoot启动过程源码解析构造SpringApplication对象SpringBoot完整的配置优先级s…

深入理解WebSocket协议

“ 一直以来对WebSocket仅停留在使用阶段&#xff0c;也没有深入理解其背后的原理。当看到 x x x was not upgraded to websocket&#xff0c;我是彻底蒙了&#xff0c;等我镇定下来&#xff0c;打开百度输入这行报错信息&#xff0c;随即看到的就是大家说的跨域&#xff0c;或…

SpringBoot帮你优雅的关闭WEB应用程序

Graceful shutdown 应用 Graceful shutdown说明 Graceful shutdown is supported with all four embedded web servers (Jetty, Reactor Netty, Tomcat, and Undertow) and with both reactive and servlet-based web applications. It occurs as part of closing the applica…

spring(七):事务操作

spring&#xff08;七&#xff09;&#xff1a;事务操作前言一、什么是事务二、事务四个特性&#xff08;ACID&#xff09;三、事务操作&#xff08;搭建事务操作环境&#xff09;四、事务操作&#xff08;Spring 事务管理介绍&#xff09;五、事务操作&#xff08;注解声明式事…

python学习——【第一弹】

前言 Python是一种跨平台的计算机程序设计语言&#xff0c;是ABC语言的替代品&#xff0c;属于面向对象的动态类型语言&#xff0c;最初被设计用于编写自动化脚本&#xff0c;随着版本的不断更新和语言新功能的添加&#xff0c;越来越多被用于独立的、大型项目的开发。 从这篇…

断言assert

assert作用&#xff1a;我们使用assert这个宏来调试代码语法&#xff1a;assert&#xff08;bool表达式&#xff09;如果表达式为false&#xff0c;会调用std::cout<<abort函数&#xff0c;弹出对话框&#xff0c;#include<iostream> #include<cassert> void…

学习 Python 之 Pygame 开发魂斗罗(八)

学习 Python 之 Pygame 开发魂斗罗&#xff08;八&#xff09;继续编写魂斗罗1. 创建敌人类2. 增加敌人移动和显示函数3. 敌人开火4. 修改主函数5. 产生敌人6. 使敌人移动继续编写魂斗罗 在上次的博客学习 Python 之 Pygame 开发魂斗罗&#xff08;七&#xff09;中&#xff0…