算法-树(1)—BST(二叉搜索树)

数据结构 : 二叉搜索树(BST) ????‍???? ????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍????????‍?????? 阅读详情

本文基于BST结构主要实现查找,删除功能
此种数据结构较为简单,主要分析添加查找删除功能
后附完整代码

1.BST定义:
1).每个结点均有键值对,其中键值实现排序;
2).每个结点的都大于它的左结点,小于它的右结点。
2. 主要实现(递归)

结点内部类Node:
`private class Node
{
    private Key key;
    private Value value;
    private Node left ,right;
    private int N;

    public Node(Key key,Value value,int N)
    {
        this.key = key;
        this.value = value;
        this.N = N;
    }
}
`

1).添加put
思想:键值不能相同的原则,所以先递归查找是否存在这样的键值,若存在,则更新value值,否则添加相应的键值对到对应的位置。
实现:

    private Node put(Node x,Key key,Value value)
    {
        if(x == null) 
            return new Node(key,value,1);
        int cmp = key.compareTo(x.key);
        if (cmp<0)
            x.left = put(x.left,key,value);
        else if (cmp>0)
            x.right = put(x.right,key,value);
        else 
            x.value = value;
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

2).删除deleteMin,delete
1.删除最小值:
查找最小值:递归查找左子树,若左子树为null,则递归右子树,查找Node.left==null的结点,次结点即为树的最小值。
删除最小值:删除最小值后,最小结点的右子树,接到最小值父结点的左子树中。

    private Node deleteMin(Node x)
    {
        if(x.left == null)
            //此处返回需要删除的最小结点的右子树(这样才能保证后面结点不丢失).
            return x.right;
        //递归到最小结点时,返回了x.right,此处令最小结点的父结点的左子树等于返回的x.right.
        //而需要删除的结点,被当成垃圾系统回收.
        x.left = deleteMin(x.left);
        //更新计数器.
        x.N = size(x.left)+size(x.right)+1;
            return x;
    }

2.删除任意结点(传入键值):
思想:首先肯定先递归查找的删除的键值(假设x结点),删除结点x时,我们需要使用到deleteMin,找到以x为父结点的子树的,用于替换x位置的结点。

    private Node delete(Node x,Key key)
    {
        if(x == null)
            return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0)
            x.left = delete(x.left,key);
        else if(cmp > 0)
            x.right = delete(x.right,key);
        else
        {
            //此处x为需要删除的结点.判断x是否为单结点,若为单结点,返回x.left或者x.right即能删除x结点.
            if(x.right == null)
                return x.left;
            if(x.left == null)
                return x.right;
            //若不为单结点.创建t结点,保存x的左右连接状态,再查找x右子树的最小结点(此结点即为新的取代x结点的结点).
            Node tmp = x;
            x = min(tmp.right);
            x.right = deleteMin(tmp.right);
            x.left = tmp.left;
        }
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

3.性能分析:
二分查找法(有序数组):
最坏:查找—lgN。插入—N
平均:查找—lgN。插入—N/2
二叉查找树:
最坏:查找—N。插入—N
平均:查找—1.39lgN。插入—1.39lgN
BST的性能与树的高度成正比。
3. 完整代码

package search;
/**
  * @author : 罗正 
  * @date time:2016年9月7日 下午9:47:08 
**/
public class BSTsearch <Key extends Comparable<Key> ,Value>{

    private Node root;
    /**
     * 内部类:树结点——Node
     * @param args
     */
    private class Node
    {
        private Key key;
        private Value value;
        private Node left ,right;
        private int N;

        public Node(Key key,Value value,int N)
        {
            this.key = key;
            this.value = value;
            this.N = N;
        }
    }

    public int size(){
        return size(root);
    }

    private int size(Node x)
    {
        if (x == null) 
            return 0;
        else 
            return x.N;
    }

    /**
     * funtion:根据传入的key值,递归查找二叉树,无则返回null.
     * @param key
     * @return
     */

    public Value get (Key key)
    {
        return get(root,key);
    }

    private Value get(Node x,Key key)
    {
        if(x == null)
            return null;
        int cmp = key.compareTo(x.key);
        if (cmp<0)
            return get(x.left,key);
        else if (cmp>0)
            return get(x.right,key);
        else
            return x.value;
    }

    /**
     * 查找key值,找到则更新,没有则添加.
     * @param key
     * @param value
     */
    public void put(Key key,Value value)
    {

        root = put(root,key,value);
    }

    /**
     * 没有则插入root的子树当中
     * @param x
     * @param key
     * @param value
     * @return
     */
    private Node put(Node x,Key key,Value value)
    {
        if(x == null) 
            return new Node(key,value,1);
        int cmp = key.compareTo(x.key);
        if (cmp<0)
            x.left = put(x.left,key,value);
        else if (cmp>0)
            x.right = put(x.right,key,value);
        else 
            x.value = value;
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

    public Key min()
    {
        return min(root).key;
    }
    private Node min(Node x)
    {
        if(x.left == null)
            return x;
        return min(x.left);
    }

    /**
     * 返回小于等于key的最大键.
     * @param key
     * @return
     */
    public Key floor(Key key)
    {
        Node x = floor(root,key);
        if(x == null)
            return null;
        return x.key;
    }
    private Node floor(Node x,Key key)
    {
        if( x == null)
            return x;
        int cmp = key.compareTo(x.key);
        if(cmp == 0)
            return x;
        if(cmp<0)
            return floor(x.left,key);
        Node t = floor(x.right,key);
        if(t != null)
            return t;
        else
            return x;

    }

    /**
     * 根据传入的int k值,查找在树中的key值,并返回
     * @param k
     * @return
     */
    public Key select(int k)
    {
        return select(root,k).key;
    }
    private Node select(Node x,int k)
    {
        if(x == null)
            return null;
        int num = size(x.left);
        if(num > k)
            return select(x.left,k);
        else if(num < k)
            return select(x.right,k-num-1);
        else 
            return x;
    }

    /**
     * 根据传入的key,查找在树中的rank.
     * @param key
     * @return
     */
    public int rank(Key key)
    {
        return rank(root,key);
    }

    private int rank(Node x,Key key)
    {
        if( x == null)
            return 0;
        int cmp = key.compareTo(x.key);
        if(cmp > 0)
            //此处不要忘了加上1+size(x.left)
            return 1+size(x.left)+rank(x.right,key);
        if(cmp < 0)
            return rank(x.left,key);
        else
            return size(x.left);
    }

    /**
     * 以下为较难实现的BST删除操作.
     * 实现步骤如下:
     * 1.保存要删除的结点链接.(如删除A,保存t = B.left).
     * 2.A指向X = min(A.left).<这个结点就是删A后,取代A位置的结点!>
     * 3.X取代A的操作,以及X位置抽取后,树变动的操作
     * 
     * deletemMin().
     * delete().
     */
    public void deleteMin()
    {
        root = deleteMin(root);
    }
    private Node deleteMin(Node x)
    {
        if(x.left == null)
            return x.right;
        x.left = deleteMin(x.left);
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

    /**
     * 删除给定的键值对key.
     * @param key
     */
    public void delete(Key key)
    {
        root = delete(root,key);
    }

    /**
     * 递归删除key,
     * 返回Node值,便于实现递归而不丢失链接.
     * @param x
     * @param key
     * @return
     */
    private Node delete(Node x,Key key)
    {
        if(x == null)
            return null;
        int cmp = key.compareTo(x.key);
        if(cmp < 0)
            x.left = delete(x.left,key);
        else if(cmp > 0)
            x.right = delete(x.right,key);
        else
        {
            //此处x为需要删除的结点.判断x是否为单结点,若为单结点,返回x.left或者x.right即能删除x结点.
            if(x.right == null)
                return x.left;
            if(x.left == null)
                return x.right;
            //若不为单结点.创建t结点,保存x的左右连接状态,再查找x右子树的最小结点(此结点即为新的取代x结点的结点).
            Node tmp = x;
            x = min(tmp.right);
            x.right = deleteMin(tmp.right);
            x.left = tmp.left;
        }
        x.N = size(x.left)+size(x.right)+1;
        return x;
    }

    public static void main(String[] args) {
        // TODO Auto-generated method stub

        BSTsearch bst = new BSTsearch<>();
        bst.put("B", "b");
        bst.put("A", "a");
        bst.put("D", "d");
        bst.put("W", "w");
        bst.put("X", "x");
        bst.put("Z", "z");
        System.out.println(bst.select(0));
        System.out.println("rank A:"+bst.rank("A"));
        System.out.println("bst size :"+bst.size());
        System.out.println("floor:"+bst.floor("Z"));
        System.out.println("min :"+bst.min());
        bst.deleteMin();
        System.out.println("min (mid):"+bst.min());
        bst.delete("B");
        System.out.println("min :"+bst.min());
        System.out.println("bst size:"+bst.size());
    }

}

算法第四版—二叉查找树

平衡二叉搜索树(AVL树)及其实现 AVL树: AVL树是良好平衡的,在一颗AVL树中,每个结点的子树的高度差距为0或者1。可以得出一个AVL树的最大高度为O(log n)。 平衡因子:右子树的高度减去左子树的高度。 左偏重:如果结点的平衡因子为-1 或更小。 右偏重:如果结点的平衡因子为+1 或更大。 旋转:一个结点重新获得平衡的过程,有4 种可能的旋转:LL、RR、LR、RL。 LL旋转:以下情况使用LL旋转 RR旋转:以下情况使用RR旋转 LR旋转:以下情况使用LR旋转 RL旋转:以下情况使用R 阅读详情

相关推荐

通俗易懂的AVL树

AVL树链表。其核心机制包括:计算平衡因子是一种自平衡二叉搜索树,通过严格限制节点左右子树高度差不超过1来防止普通BST退化为(BF=右高-左高),当|BF|>1时触发旋转操作(LL/RR单旋,LR/RL双旋),确保增删查操作效率稳定在O(logN)。相比普通BST,AVL树查询更快但维护成本高;相比红黑树,它平衡更严格但旋转更频繁。本文详解了AVL树的平衡原理、四种旋转策略及Java实现,强调其作为平衡树基础的重要教学价值。

2502_93175209的博客 310

数据结构——搜索二叉树(BST)

作者的搜索二叉树(BST)的相关笔记

Cym20231111的博客 1971

树系列之BST树 数据结构 完整源码

完整版二叉搜索树 /* * 参考资料: * <<算法导论>>, <<C算法: 第一卷>> * 此程序经过大量测试, 测试类在 main.cpp文件中 * 类型 T 必须重载 < > == 比较运算符号 */

数据结构——二叉搜索树(BST)

二叉搜索树(BST,Binary Search Tree)又称二叉排序树、二叉查找树首先,它可以是一棵空树;1. 非空左子树的所有键值小于其根节点的键值2. 非空右子树的所有键值大于其根节点的键值3. 左右子树也分别为二叉搜索树二叉搜索树一般不支持key值冗余(不允许有重复的key值)如图为一棵标准的二叉搜索树:相比较于常规的二叉树,二叉搜索树具有明显的大小区分度,对二叉搜索树进行中序遍历,所获取的键值便是严格从小到大排序的。

jiajixi的博客 1902

BST树节点的插入,删除和查找

实现了BST树节点的插入,删除和查找,其中删除只实现了一种,即用前驱替换,另外一种用后继替换没有实现。

从零构建工业级SPI-CAN网关:CH347与CH9431的软硬件协同设计实战

本文详细介绍了基于CH347和CH9431芯片构建工业级SPI-CAN网关的完整方案。通过硬件架构设计、Linux驱动定制、并发处理优化和EMC抗干扰测试,实现高可靠性通信网关,适用于工业自动化和汽车电子等严苛环境。

spark7igniter的博客 633

树型结构(BST)

树型结构往往是用于描述分层级,类似组织架构关系之类的非线性的数据结构

m0_70935583的博客 1037

ROS2新手必看:5分钟搞定Gazebo机器人仿真环境搭建(含避坑指南)

本文为ROS2新手提供了在Gazebo中快速搭建机器人仿真环境的详细指南。内容涵盖ROS2与Gazebo的协同架构理解、基础环境配置、机器人模型构建、传感器集成以及环境创建,并包含实用的避坑指南和调试技巧,帮助开发者高效掌握物理仿真技术。

weixin_29100927的博客 430

高级数据结构之BST(一)

1、树的节点包含一个数据元素,以及若干指向其子树的分支。节点拥有的子树的数量称为节点的度。节点的最大层次称为树的深度或高度。 2、二叉树是一种树形结构,其特点是每个节点至多有两棵子树,且子树有左右之分,次序不能随意颠倒。 3、满二叉树:一棵深度为k且有2^k - 1个节点的二叉树,称之为满二叉树。 4、完全二叉树:对一个深度为k,节点个数为n的二叉树,当且仅当每个节点都与深度为k的满二叉树中...

禾露悠悠摇的博客 1922

ESP32-S3 + TB6600驱动42步进电机:从基础接线到AccelStepper库平滑加减速实战

本文详细介绍了如何使用ESP32-S3开发板和TB6600驱动器控制42步进电机,从基础接线到利用AccelStepper库实现平滑加减速控制。内容涵盖硬件连接、基础驱动代码、AccelStepper库的安装与参数调优,以及高级技巧与故障排除,帮助创客实现工业级精准控制。

weixin_42632434的博客 287

从零搭建Simulink-Adams联合仿真平台:实现电机转速的精准闭环控制

本文详细介绍了从零搭建Simulink-Adams联合仿真平台的完整流程,旨在实现电机转速的精准闭环控制。通过将Simulink的控制算法与Adams的物理模型相结合,构建了一个包含真实机械效应的数字孪生系统。文章涵盖了Adams物理模型构建、接口定义、Simulink控制闭环搭建、PID参数调试以及常见避坑指南,为机电系统仿真提供了实用的工程实践指导。

weixin_29189373的博客 154

linux 自平衡AVL树

本文介绍了AVL树的基本概念和特性,进行了有关算法的实现,并通过示例程序演示了AVL树是如何实现自平衡的。

gogo0707的博客 406

CHB-MIT波士顿儿童医院癫痫EEG脑电数据处理(一)

CHB-MIT癫痫EEG脑电数据处理CHB-MIT头皮脑电图数据介绍CHB-MIT头皮脑电图数据下载CHB-MIT头皮脑电图数据处理提取原始数据滤波(0.1~50hz)数据分块(时间窗口) CHB-MIT头皮脑电图数据介绍 该数据库收集自波士顿儿童医院,其中包括患有难治性癫痫发作的儿科患者的脑电图记录。停用抗癫痫药物后最多持续几天对受试者进行监测,以表征其癫痫发作并评估其对手术干预的候选资格。 从22位受试者中收集了23个病例的记录(5例男性,3至22岁; 17例女性,1.5至19岁)。 (案例chb21是

AI_DOG的博客 1万+

Raspberry Pi Pico硬件开发入门:MicroPython固件烧录与REPL实战

MicroPython是一种专为微控制器设计的轻量级Python实现,其核心价值在于将高级语言的开发效率与嵌入式硬件的底层控制能力相结合。它通过字节码解释器在有限资源(如RP2040的264KB SRAM)中运行,依赖UF2固件格式与硬件Bootloader深度协同,实现‘拖拽即烧录’的极简部署流程。技术优势体现在透明的GPIO操作、原生USB HID支持及对PIO等硬件特性的直接访问,显著降低硬件开发门槛。典型应用场景包括传感器数据采集、LED/PWM控制、I2C外设驱动及USB设备模拟等快速原型验证。本

weixin_34194087的博客 305

实战解析:从Innovus到Calibre的LVS错误排查全流程

本文详细解析了从Innovus到Calibre的LVS错误排查全流程,涵盖物理验证关键步骤与工具链协同。通过实战案例分享,重点解决器件不匹配、连接性错误等常见问题,并提供GDS导出规范、网表修正策略等实用技巧,帮助工程师高效完成芯片设计物理验证。

9o8p7i6u5y的博客 1038

AI原生应用API编排:如何实现高效的权限管理?

随着GPT-4、Claude 3等大模型的普及,AI原生应用(从设计之初就以AI为核心的应用)正从“概念”走向“落地”。依赖大量外部API的协同工作(如用户身份API→大模型生成API→支付API→存储API)。但随之而来的挑战是:如何在复杂的API调用链中,确保每个环节的权限合规?本文将聚焦这一问题,覆盖API编排的基础逻辑、权限管理的核心机制(如RBAC/ABAC)、实战工具链(如OPA策略引擎),以及常见场景的解决方案。本文将按照“场景引入→核心概念→原理拆解→实战演练→趋势展望”的逻辑展开。

大数据洞察的博客 452

C语言角色互换指针,树移动指针中两个随机选择节点的角色交换算法

我创建了一个算法,它的目的应该是,给定BST中的两个节点A和B,它通过简单地移动指针来切换这两个节点的角色(或树中的位置)。在我对BST的表示中,我使用了一个双链接连接(即a.parent==B和(B.left==a)或(B.right==a))。我不确定这是否完全正确。我把算法分为两种情况。在A和B直接相连(A是B的父项,B是A的父项)所有其他案例对于前面的每个例子,我都创建了一个嵌套函数。我想...

weixin_42525569的博客 405

第11节:GPU 线程层级:线程、线程块、网格

层级标识变量功能线程threadIdx执行单元,处理数据线程块blockIdx管理多个线程,提供共享内存网格管理多个 blockGPU 编程中,合理安排线程层级,是提升性能的关键。

yumeiguo的博客 212

[Swift]LeetCode95. 不同的二叉搜索树 II | Unique Binary Search Trees II

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★➤微信公众号:山青咏芝(shanqingyongzhi)➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/)➤GitHub地址:https://github.com/strengthen/LeetCode➤原文地址:https://www.cnblogs.com/streng...

weixin_30596165的博客 110

霍尼韦尔SoftMaster使用说明

霍尼韦尔SoftMaster使用说明

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Inorder Traversal a BST with Constant Extra Space

1. Modify the BST During the Traversal出自: http://stackoverflow.com/questions/5496464/write-a-non-recursive-traversal-of-a-binary-search-tree-using-constant-space-andUse O(n) time and canstant space.Id

y417244146的博客 717

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

leetcode tree of good ideas(树)

题目1:Convert Sorted Array to Binary Search Tree(树,递归算法) Given an array where elements are sorted in ascending order, convert it to a height balanced BST. For this problem, a height-balanced binary tree...

weixin_44052726的博客 163

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

leetcode 1569. Number of Ways to Reorder Array to Get Same BST(重新排序数组以获得相同 BST 的方法数)

递归,组合,杨辉三角

蓝羽飞鸟的博客 295

LC-不同的二叉搜索树

不同的二叉搜索树 //给定一个值n,能构建出多少不同的值包含1...n的二叉搜索树(BST)? class Solution { public: /** * * @param n int整型 * @return int整型 */ /*考虑根节点,设对于任意根节点k,有f(k)种树的可能。 比k小的k-1个元素构成k的左子树。则左子树有f(k-1)种情况。 比k大的n-k个元素构成k的右子树。则右子树有f(n-k)种情况。 易知,左右子树相互独立,所以f(k)=f(k-1)

qq_41105501的博客 191

LeetCode | Unique Binary Search Trees II(构建二叉搜索树)

Given n, generate all structurally unique BST's (binary search trees) that store values 1...n. For example, Given n = 3, your program should return all 5 unique BST's shown below. 1 3

solar一抹阳光的专栏 622

(LeetCode-Hot100)96. 不同的二叉搜索树

本题是卡特兰数的经典应用场景之一。固定根后,左右子树独立,总数为乘积。动态规划状态转移方程体现了“分而治之”的思想。扩展思考:若要求生成所有不同的 BST(LeetCode 95 题),则需回溯构造,而非仅计数。💡记忆点:看到“不同结构的二叉搜索树数量”,立刻联想到卡特兰数!

小飞的博客 716

树--06---二叉树--03---二叉搜索树(BST)--最大深度问题、折纸问题

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录最大深度问题需求:API求最大深度:实现步骤:代码:测试;折纸问题需求:分析:实现步骤:构建深度为N的折痕树:每一次对折,所有叶子节点都需增加其左子结点和右子结点代码: 最大深度问题 需求: 给定一棵树,请计算树的最大深度(树的根节点到最远叶子结点的最长路径上的结点数); 上面这棵树的最大深度为4。 API求最大深度: 实现步骤: 如果根结点为空,则最大深度为0; 计算左子树的最大深度; 计算右子树的最大深度; 当前树的

时光里的博客 90
上一篇: 排序算法(3)—优先队列,堆排序
下一篇: 算法-树(2)—深入红黑树
luoz_python
博客等级 码龄10年 57粉丝 47原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值