二叉搜索树桶排序

news2024/11/23 13:26:29

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

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

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

*它的左右子树也分别是一棵二叉搜索树

*二叉搜索树的中序遍历是有序的

*查找某一个值,相当于类似二分查找

 2、插入一个元素

*如果是空树的情况下
创建一个节点,让root直接引用就可以了

*根据二叉搜索树的性质,判断当前节点值与传入值的大小,让当前节点移动到左边或者右边

*在current遍历的过程中,要用一个prev记录他的父节点

*当current==null时,根据传入的元素值,与父节点的值作比较,插入到左或者右

 3、删除元素操作

设删除的节点为cur,待删除的双亲节点为parent

3.1、cur.left==null

*cur是root则root=cur.right

*cur不是root,cur是parent.left,则parent.left=cur.right

*cur不是root,cur是parent.right,则parent.right=cur.right

3.2、cur.right==null

*cur是root,则root=cur.left

*cur不是root,cur是parent.left,则parent.left=cur.left

*cur不是root,cur是parent.right,则parent.right=cur.left

3.3、cur.left!=null&&cur.right!=null


public class BinarySearchTree {
    //定义节点类
    public static class TreeNode {
        int value;
        TreeNode left;
        TreeNode right;

        public TreeNode(int value) {
            this.value = value;
        }
    }

    //定义根节点
    public TreeNode root;

    //查找指定值
    public boolean search(int value) {
        //1、判断根节点是否为空
        if (root == null) {
            return false;
        }
        //2、定义一个用来遍历的节点
        TreeNode current = root;
        while (current != null) {
            //3、判断节点值是否相等
            if (value == current.value) {
                return true;
            }
            //4、根据value和当前节点的值判断继续向左或向右移动
            if (value < current.value) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return false;
    }

    /**
     * 插入元素
     *
     * @param value 要插入的值
     * @return
     */
    public boolean insert(int value) {
        TreeNode node = new TreeNode(value);
        //1、判断根节点是否为空
        if (root == null) {
            root = node;
            return true;
        }
        //2、遍历二叉搜索树
        TreeNode current = root;
        //用来记录current节点
        TreeNode prev = null;
        while (current != null) {
            //判断是否相等
            if (current.value == value) {
                //如果相等直接返回
                return false;
            }
            //找到真正插入的位置
            prev = current;
            if (current.value > value) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        //当current==null时,prev就在一个叶子节点的位置
        //根据prev的值确定新节点的位置
        if (prev.value> value) {
            prev.left = node;
        } else {
            prev.right = node;
        }
        return true;
    }

    /**
     * 删除指定的元素
     *
     * @param value
     * @return
     */
    public boolean remove(int value) {
        //条件判空
        if (root == null) {
            return false;
        }
        //找到要删除的元素
        TreeNode current = root;
        TreeNode parent = null;
        while (current != null) {
            if (current.value == value) {
                removeNode(parent, current);
                return true;
            }
            //记录父节点
            parent = current;
            if (value < current.value) {
                current = current.left;
            } else {
                current = current.right;
            }
        }
        return false;
    }

    //删除节点
    private void removeNode(TreeNode parent, TreeNode current) {
        if (current.left == null) {
            //当左孩子节点为空时进入
            if (current == root) {
                //把要删除的右节点赋给root
                root = current.right;
            } else if (current == parent.left) {
                //当前节点是父节点的左节点时
                parent.left = current.right;
            } else {
                //当前节点是父节点的右节点时
                parent.right = current.right;
            }
        } else if (current.right == null) {
            //当前节点时根结点时
            if (current == root) {
                root = current.left;
            } else if (current == parent.left) {
                //当前节点是父节点的左孩子节点时
                parent.left = current.left;
            } else {
                //当前节点是父节点的右孩子节点时
                parent.right = current.left;
            }
        } else {
            //用来定义便利的几个变量
            TreeNode target = current.right;
            TreeNode parentTarget = current;
            //向左去找最小值
            while (target.left != null) {
                parentTarget = target;
                target = target.left;
            }
            //到达叶子节点
            current.value = target.value;
            //删除target节点
            if (target == parentTarget.left) {
                parentTarget.left = target.right;
            } else {
                parentTarget.right = target.right;
            }
        }
    }

    /**
     * 中序遍历
     *
     * @param node
     * @return
     */
    public String inOrder(TreeNode node) {
        StringBuilder sb = new StringBuilder();
        if (node == null) {
            return sb.toString();
        }
        //先处理左
        String left = inOrder(node.left);
        sb.append(left);
        //处理根节点
        sb.append(node.value+" ");
        //处理右
        String right=inOrder(node.right);
        sb.append(right);
        return sb.toString();
    }
}

4、测试类


public class TestBinaryTree {
    public static void main(String[] args) {
        int[] array={5,3,7,1,4,6,8,0,2,9};
        BinarySearchTree binarySearchTree=new BinarySearchTree();
        for(int i=0;i<array.length;i++){
            binarySearchTree.insert(array[i]);
        }
        System.out.println(binarySearchTree.inOrder(binarySearchTree.root));
    }
}

6、桶排序是计数排序的扩展版本,计数排序可以看成每个桶只存储相同元素,而桶排序中每个桶只存储一定范围的元素,通过映射函数,将待排序数组中的每一个元素映射到各个对应的桶中,对每个桶中的元素进行排序,最后将非空桶中的元素逐个放入原序列中。

桶排序需要尽量保证元素分散均匀,否则当所有数据放在一个桶中,桶排序失效

时间和空间复杂度取决于 桶中应用的排序算法


public class HashBucket {
    //定义一个节点对象
    public static class Node{
        int key;
        int value;
        Node next;
        public Node(int key,int value){
            this.key=key;
            this.value=value;
        }
    }
    //定义哈希桶
    private Node[] bucket;
    //当前有效的元素个数
    static int size;
    //定义负载因子
    private final float DEFAULT_LOAD_FACTORY=0.75f;
    public HashBucket(){
        bucket=new Node[8];
    }

    /**
     * 写入操作
     * @param key
     * @param value
     * @return
     */
    public int put(int key,int value){
        //1、根据key的值计算下标
        int index=key%bucket.length;
        //2、拿到对应下标的元素,这个元素就是链表的头节点
        Node current=bucket[index];
        //3、遍历链表是否存在key相同的元素
        while(current!=null){
            //找到的情况下
            if(current.key==key){
                int oldValue=current.value;
                current.value=value;
                return oldValue;
            }
            current=current.next;
        }
        //4、遍历完链表之后,创建新节点
        Node node=new Node(key,value);
        //5、让新节点的next引用当前下标的节点
        node.next=bucket[index];
        //6、让当前下标存放新节点
        bucket[index]=node;
        //7、有效个数加一
        //size是桶的有效个数
        size++;
        //8、判断当前有效桶的个数是否超过负载因子
        if(locaderFactor()>=DEFAULT_LOAD_FACTORY){
            //9、扩容
            resize();
        }
        return 0;
    }

    /**
     * 扩容数组
     */
    private void resize() {
        //1、按二倍大小扩容
        Node[] array=new Node[bucket.length*2];
        //2、取出所有元素,重新hash
        for (int i = 0; i < bucket.length; i++) {
            //2.1、取出hash桶中第一个节点,向下遍历
            Node current=bucket[i];
            while(current!=null){
                //2.2、记录下一个节点
                Node nextNode=current.next;
                //2.3、对当前节点进行重新hash
                int index=current.key/bucket.length;
                //2.4、把节点放到新的桶位中
                current.next=array[index];
                array[index]=current;
                //2.5、移动到下一个节点
                current=nextNode;
            }
        }
        //更新成员变量为新的数组
        bucket=array;
    }

    private float locaderFactor() {
        return size*1.0f/bucket.length;
    }

    /**
     * 根据key查找相应的value
     * @param key
     * @return
     */
    public int get(int key){
        //根据key算出响应的下标
        int index=key%bucket.length;
        //开始遍历下标里面的链表
        Node current=bucket[index];
        while(current!=null){
            if(current.key==key){
                return current.value;
            }
            //向后移动节点
            current=current.next;
        }
        return -1;
    }
}

 测试类:



public class TestHashBucket {
    public static void main(String[] args) {
        HashBucket hashBucket=new HashBucket();
        hashBucket.put(1,2);
        hashBucket.put(2,3);
        hashBucket.put(3,4);
        hashBucket.put(4,5);
        hashBucket.put(5,6);
        System.out.println("key :"+hashBucket.get(2));
        System.out.println("key :"+hashBucket.get(20));
    }
}

 

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

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

相关文章

皮卡丘CSRF

1.CSRF&#xff08;get&#xff09; 首先看提示&#xff0c;我们选择用户kobe&#xff0c;密码123456登录 点击修改个人信息&#xff0c;假如用户要把住址改为shanxi 再点击submit&#xff0c;同时用bp抓包&#xff0c;我们可以看到是get请求&#xff0c;数据包含在URL之中 将…

web服务器有哪些

<1>什么是web服务器 “网络服务”&#xff08;Web Service&#xff09;的本质&#xff0c;就是通过网络调用其他网站的资源。 Web Service架构和云 如果一个软件的主要部分采用了”网络服务”&#xff0c;即它把存储或计算环节”外包”给其他网站了&#xff0c;那么我…

【Linux网络编程】HTTPS协议原理

https协议原理 一、HTTPS是什么二、基本概念2.1、什么是加密2.2、为什么要加密 三、常见的加密方式四、数据摘要(指纹)&&数字签名五、HTTPS的工作过程探究方案&#xff08;1&#xff09;&#xff1a;只使用对称加密方案&#xff08;2&#xff09;&#xff1a;只使用非对…

论文笔记--PANGU-α

论文笔记--PANGU-α: LARGE-SCALE AUTOREGRESSIVE PRETRAINED CHINESE LANGUAGE MODELS WITH AUTO-PARALLEL COMPUTATION 1. 文章简介2. 文章概括3 文章重点技术3.1 Transformer架构3.2 数据集3.2.1 数据清洗和过滤3.2.2 数据去重3.2.3 数据质量评估 4. 文章亮点5. 原文传送门6…

旧改快讯--罗湖蔡屋围项目二期子项目D、E启动行政征收

蔡屋围城市更新统筹片区蔡屋围&#xff08;城中村&#xff09;项目二期子项目D&#xff08;南村片区&#xff09;、子项目E&#xff08;南村东片区&#xff09;房屋征收提示 5月9日&#xff0c;深圳市罗湖区城市更新和土地整备局发布关于罗湖区桂园街道蔡屋围城市更新统筹片区…

[架构之路-204]- 常见的需求分析技术:结构化分析与面向对象分析

目录 前言&#xff1a; 1 1 . 3 需求分析概述 导言&#xff1a; 11.3.1需求分析的任务 (1) 绘制系统上下文范围关系图&#xff1a; (2) 创建用户界面原型&#xff1a; (3) 分析需求的可行性&#xff1a; (4) 确定需求的优先级&#xff1a; (5) 为需求建立模型&#xf…

DetailGAN

1.摘要 本文提出了一种基于保留细节的对抗学习的红外和可见光图像融合的端到端模型。它能够克服传统融合方法中基于活动级别测量和融合规则的手动和复杂设计的局限性。考虑到红外和可见光图像的特定信息&#xff0c;我们设计了两个损失函数&#xff0c;包括细节损失和目标边缘…

738.单调递增的数字;968.监控二叉树

贪心 738.单调递增的数字思路:代码 968.监控二叉树思路:如何放置&#xff0c;才能让摄像头最小的呢&#xff1f; 738.单调递增的数字 思路: 举例&#xff0c;数字&#xff1a;332&#xff0c;从前向后遍历的话&#xff0c;那么就把变成了329&#xff0c;此时2又小于了第一位的…

mysql密码字段类型

数值 mysql 的数值数据类型可以大致划分为两个类别&#xff0c;一个是整数&#xff0c;另一个是浮点数或小数。 许多不同的子类型对这些类别中的每一个都是可用的&#xff0c;每个子类型支持不同大小的数据&#xff0c;并且 MySQL 允许我们指定数值字段中的值是否有正负之分(U…

【owt】WebrtcNode, subscribe流程

subscribe流程 1. AmqpClient - New message received 2023-04-26T21:54:18.415 - DEBUG: AmqpClient - RpcServer New message received {method: subscribe,args: [b149e44bb10d4e91bd162a8c6806ae7b,webrtc,{transportId: b149e44bb10d4e91bd162a8c6806ae7b,tracks: [Arr…

C4网络技术挑战赛 智慧园区方案分析

添加链接描述 智慧园区网络 市场现状: 网络与应用系统多厂商、多平台、多系统,导致IT部门管理运维复杂&#xff0c;效率低下. 统一运维管理&#xff1f; 无线网络与物联网的双网合一&#xff1f; ps&#xff1a; 无线网络(英语:Wireless network)指的是任何型式的无线电计…

【Mysql数据库从0到1】-入门基础篇--mysql基本使用

【Mysql数据库从0到1】-入门基础篇--mysql基本使用 &#x1f53b;一、Mysql5.7 VS Mysql8.0 详解1.1 ⛳字符编码1.2 ⛳用户的创建与授权1.3 ⛳ 认证插件1.4 ⛳ 隐藏索引1.5 ⛳ 持久化设置1.6 ⛳ 通用表表达式&#xff08;Common Table Expressions&#xff09;1.7 ⛳ 性能提升1…

redis缓存单体服务测试本地锁失效问题

测试1&#xff1a;锁释放之后向redis缓存存入数据 //TODO 产生堆外内存溢出 OutOfDirectMemoryError//gulimall.com查询分类Overridepublic Map<String, List<CategoryLevel2Vo>> getCatelogJson() {/*** 问题 &#xff1a;解决办法* 1.缓存穿透 高并发情况下查询缓…

Java学习方式分享

哈喽&#xff0c;大家好呀&#xff0c;好久不见&#xff01;咱依然是那个腼腆害羞内向社恐文静、唱跳rap篮球都不大行的【三婶er】 坦白地说&#xff0c;今天是偶然看到C站这个活动的&#xff0c;这个主题我颇有感触&#xff0c;刚学java时的场景&#xff0c;历历在目。所以今天…

ChatGPT常见的报错解决方法(全网最全解决方法)

因为最近在使用ChatGPT的过程中&#xff0c;时常会出现一些错误提示&#xff0c;为了方便自己快速解决问题&#xff0c;所以也搜集了一些其他博主的解决方法&#xff0c;以下是整理的内容。 目录 1、拒绝访问 2、Access denied错误 3、We have detected suspicious 错误 4…

leetcode_19_相同的树

bool isSameTree(struct TreeNode* p, struct TreeNode* q){if(pNULL && qNULL)return true;//其中一个为空if(pNULL || qNULL)return false;//都不为空,且首节点的值不相等if(p->val ! q->val)return false;//p和q的值相等&#xff0c;分别比较左子树和右子树re…

如何使用debugHunter发现隐藏调试参数和Web应用程序敏感信息

关于debugHunter debugHunter是一款针对Web应用程序隐藏调试参数和敏感信息的识别扫描工具,该工具本质上是一个Chrome扩展,可以帮助广大研究人员扫描目标Web应用程序/网站以查找调试参数,并在发现了包含修改响应的URL时发送通知。该扩展利用了二分查找算法来有效地确定导致…

《基于Linux物联网综合项目》常见问题汇总fae

关于该课程说明 1&#xff09;本课程目标 通过web浏览器访问服务器&#xff0c;实现登录、注册、数据库操作、远程操控硬件、采集环境信息、远程监控、拍照、图片显示等功能。 将单片机、linux、html、摄像头、数据库等知识点融入到一个项目中。 2&#xff09;什么群体适合学…

JVM 虚拟机栈介绍

一、虚拟机栈&#xff08;VM Stack&#xff09; 1.1&#xff09;什么是虚拟机栈 虚拟机栈是用于描述java方法执行的内存模型。 每个java方法在执行时&#xff0c;会创建一个“栈帧&#xff08;stack frame&#xff09;”&#xff0c;栈帧的结构分为“局部变量表、操作数栈、动态…

JavaScript实现以数组方式输入数值,输出最大的数的代码

以下为实现以数组方式输入数值&#xff0c;输出最大的数的程序代码和运行截图 目录 前言 一、以数组方式输入数值&#xff0c;输出最大的数 1.1 运行流程及思想 1.2 代码段 1.3 JavaScript语句代码 1.4 运行截图 前言 1.若有选择&#xff0c;您可以在目录里进行快速查找…