Java进阶07集合(续)

Java进阶07 集合(续)

一、数据结构(树)

1、关于树

1.1 相关概念
  • 节点:树中每个单独的分支

  • 节点的度:每个节点的子节点数量

  • 树高:树的总层数

  • 根节点:最顶层节点

  • 左子节点:左下方的节点

  • 右子节点:右下方的节点

  • 左子树:节点左下方连接的全部节点

  • 右子树:节点右下方连接的全部节点

1.2 二叉树&二叉查找树

  • 普通二叉树

    树中任意节点的度都<=2

  • 二叉查找树

    又称二叉排序树、二叉搜索树。其特点是:①首先必须是二叉树;②任意节点左子树上的值均小于当前节点值;③任意节点右子树上的值都大于当前节点值;

    二叉查找树的节点如果都挂在同一边,会产生瘸腿现象,那么它的查询效率就和普通的单链表一样了,为了解决这个问题,引入平衡二叉树

1.3 平衡二叉树

在是二叉查找树的前提下,任意节点的左右子树高度差不超过1,即为平衡二叉树。由于平衡二叉树的这个特点,每次往该树中加入新的节点时,就可能会对其平衡性有影响。当添加了某个节点后,改变了该树的平衡性,则会触发旋转机制来保证平衡性

  • 旋转规则

    确定支点:从添加的结点开始,不断往父节点找不平衡的节点,这个点就是支点

    • 左旋(右右加入造成不平衡)

      case1.支点没有左子节点

      把支点左旋降级,变成左子节点;晋升原来的右子节点

      case2.支点有左子节点

      将根节点的右侧往左拉;原先的右子节点变成新的父节点,并把多余的左子节点让出,给已经降级的根节点当右子节点

    • 右旋(左左加入造成不平衡)

      case1.支点没有右子节点

      把支点右旋降级,变成右子节点;晋升原来的左子节点

      case2.支点有右子节点

      将根节点的左侧往右拉;原先的左子节点变成新的父节点,并把多余的右子节点让出,给已经降级的根节点当左子节点

  • 需要旋转的四种情况

    左左意思为根节点的左子树的左子树加入导致的不平衡,其余三种情况类似

    • 左左:一次右旋

    • 左右:先局部左旋,再整体右旋

    • 右右:一次左旋

    • 右左:先局部右旋,再整体左旋

2、红黑树

2.1 红黑树的概念

红黑树是一种自平衡的二叉查找树,是一种特殊的二叉查找树,红黑树的每一个节点上都有存储位表示节点的颜色,节点颜色非黑即红。红黑树不是高度平衡的,它的平衡是通过”红黑规则“实现的。

2.2 红黑规则

①每一个节点是红色或黑色

根节点必须是黑色

③如果一个节点没有子节点或父节点,则该节点相应的指针属性值为Nil,这些Nil视为叶节点,每个叶节点(Nil)是黑色的

④如果某一个节点是红色,那么它的子节点必须是黑色(不能出现两个相邻的红节点

⑤对每一个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点

助记口诀:左根右、根叶黑、不红红、黑路同
  • 左根右:左子树节点值<=根节点值<=右子树节点值

  • 根叶黑:根节点和叶节点(外部节点Nil)均是黑色的

  • 不红红:不能出现两个相邻的红节点

  • 黑路同:从某个节点出发,一条路走到黑(即走到它的后代叶节点上)经过的黑色节点数都相同

2.3 添加节点规则

3、动画演示网站

Data Structure Visualization (usfca.edu)

二、TreeSet集合

1、作用

对集合中的元素进行排序操作(底层红黑树实现);且属于Set派系,不允许存储重复数据,可以去重

1.1 综合案例

需求:键盘录入一个字符串,对字符串中的字符去重,并排序

public class TreeSetTest1 {
    public static void main(String[] args) {
        System.out.println("请输入:");
        String content = new Scanner(System.in).nextLine();
​
        //1、将字符串拆分为字符数组,方便获取每一个字符
        char[] chars = content.toCharArray();
        //2、准备TreeSet集合用于排序和去重
        TreeSet<Character> set = new TreeSet<>();
​
        //3、遍历字符数组,并将每一个字符添加到集合
        for (char c : chars) {
            set.add(c);
        }
​
        //4、多次拼接且不知道拼接次数,创建StringBuilder拼接
        StringBuilder sb = new StringBuilder();
        
        //注意:Set集合遍历方式只有三种(迭代器、增强for、foreach方法)
        set.forEach(c->sb.append(c));
​
        //展示拼接后的内容
        System.out.println(sb);
    }
}

2、排序方式

2.1 默认排序方式
  • Integer类,默认按数值大小排序

  • String类,默认按照其对应的编码表中的整数值逐个比较,均相同的会按照长度比较,短的在前

    TreeSet<String> set1 = new TreeSet<>();
     set1.add("aaa");
     set1.add("aaaa");
     set1.add("aab");
     set1.add("cde");
    ​
     System.out.println(set1);
    ​
    //排序结果为:aaa aaaa aab cde
2.2 自然排序
  • 类实现Comparable接口

  • 重写CompareTo方法

  • 根据方法的返回值,来组织排序规则(返回负数往左,返回正数往右,返回0不存)

    public class TreeSetDemo2 {
        public static void main(String[] args) {
            TreeSet<Student> set = new TreeSet<>();
    ​
            set.add(new Student("张三",23));
            set.add(new Student("李四",24));
            set.add(new Student("王五",25));
    ​
            System.out.println(set);
        }
    }
    ​
    //Student类要实现Comparable接口,重写compareTo方法的内部逻辑,此处年龄为主要排序依据,姓名为次要排序依据
    @Override  //年龄正序
    public int compareTo(Student o) {
        int ageResult = this.age-o.age;   //按年龄正序排列   倒序为o.age-this.age
        int nameResult = ageResult == 0 ? this.name.compareTo(o.name) : ageResult;
        //同名同年龄的需要保留,返回1或-1都无所谓,因为内容一样,谁前谁后不重要
        return nameResult == 0 ? 1 : nameResult;
    }
2.3 比较器排序(覆盖自然排序)
  • 在TreeSet的构造方法中,传入Compartor接口的实现类对象

  • 重写compare方法

  • 根据方法的返回值,来组织排序规则(返回负数往左,返回正数往右,返回0不存)

    public class TreeSetDemo3 {
        /*
           需求:对字符串进行排序,根据字符串的长度,从大到小排序
        */
        public static void main(String[] args) {
            //String类为Java写好的类,已具备自然排序,但不是我想要的排序规则,需要比较器排序
            TreeSet<String> set = new TreeSet<>(new Comparator<String>() {
                
                //重写compare方法
                @Override
                public int compare(String o1, String o2) {
                    //按长度倒序排列    o1.xxx-o2.xxx  正序  
                    int lengthResult = o2.length()-o1.length();
                    return lengthResult==0?o2.compareTo(o1):lengthResult;
                }
            });
    ​
            set.add("aaa");
            set.add("aa");
            set.add("bbbb");
            set.add("bb");
            set.add("aaaa");
    ​
            System.out.println(set);
        }
    }

3、排序如何选择

Java已经写好的类(如String、Integer、Double...)大多数都具有自然排序的规则(String默认按字典顺序、Integer默认升序、Double默认升序),这些规则放在源码中,我们无法修改其比较规则,如果我们要实现的排序规则跟自然排序不一样,此时需要使用比较器排序来覆盖自然排序规则。因为当同时具备自然排序和比较器排序时,会优先按照比较器进行排序操作;

4、利用TreeSet集合降序排列ArrayList

方法说明
static <T> void sort(T[] a,Comprtor<? super T> c)根据指定比较器产生的顺序指定对象数组进行排序
public class ArraysDemo {
    public static void main(String[] args){
        //利用集合TreeSet集合方法对数组降序排列
        Integer[] arr3 ={11,55,33,22,44};
        Arrays.sort(arr3, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o2-o1;     //o2-o1降序
            }
        });
        System.out.println(Arrays.toString(arr3));
    }
}

三、HashSet集合

1、关于HashSet底层

集合底层采取哈希表存储数据,JDK8之前的哈希表是数组+链表;JDK8之后的哈希表是数组+链表+红黑树。哈希表是一种对于增删改查数据性能都比较好的结构

2、配合去重

HashSet特点就是去重。为了保证元素唯一,必须同时重写HashCode和equals方法!!!

2.1 配合去重流程

往集合中添加对象→→→调用对象的HashCode方法**,计算出一个应存入的索引地址→→→查看该位置上是否已存在元素→→→不存在则直接存;存在,调用equals方法比较内容→→→内容不同,存入集合;内容相同,不存入。

2.2 HashCode方法
  • 该方法底层调用了C++代码计算出一个随机数(常被人称为地址值)

  • 是JDK根据某种规则算出来的int类型的整数

  • 我们不必太过关注其内部实现,可以把它简单的理解为会计算出某个对象对应的整数值

  • 为了避免存入的时候元素都堆积在同一个索引位置,因此hashcode方法的重写就显得格外重要

    ⭐重写改造原则(降低索引冲突)⭐

    将对象的所有属性值都带入运算

    • 对象的属性相同,返回哈希值一定相同

    • 对象的属性不同,返回哈希值尽量不同

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

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

相关文章

6层板学习笔记2

说明:笔记基于6层全志H3消费电子0.65MM间距BGA 67、多层板的电源建议直接大面积铺铜,不建议走线,铺铜充分满足其载流能力 68、凡亿推荐表层1OZ的铜厚线宽20MIL能承载1A的电流,内层0.5OZ的铜厚线宽为40MIL能承载1A的电流,过孔直径20MIL(0.5MM)能承载1A左右的电流,实际设…

typescript的入门到吐槽:看了typescript,发现前端真的卷,

typescript TypeScript 是一种由微软开发的自由和开源的编程语言。它是 JavaScript 的一个超集&#xff0c;而且本质上向这个语言添加了可选的静态类型和基于类的面向对象编程。 TypeScript 与 JavaScript 的区别 其实就是对JavaScript的封装&#xff0c;把一个弱类型语言封…

remmina无法连接远程桌面,Remmina无法连接远程桌面的原因与解决办法

在解决Remmina无法连接远程桌面的问题时&#xff0c;我们需要考虑多种可能的原因&#xff0c;并采取相应的解决办法。以下是一些常见的原因及其对应的解决方案&#xff1a; 1、网络问题 原因&#xff1a;不稳定的网络连接或中断可能导致无法建立远程桌面连接。 解决办法&#x…

MySQL数据库---增删查改汇总

前言 欢迎来到我的博客 个人主页:北岭敲键盘的荒漠猫-CSDN博客 本文着重整理MySQL数据库增删查改功能 主要是整理语法 争取做到要用什么语法 可以快速找到复制粘贴 增添语法 INSERT into tab(列名,列名,列名) values(内容,内容,内容); 插入一行数据 INSERT into tab(列名,…

Kubernetes最小单元Pod介绍及配置

1.1 Pod介绍 Pod是Kubernetes中的一个基本构建块&#xff0c;它是一个逻辑主机&#xff0c;用于托管一个或多个容器。 Pod中的容器共享网络和存储资源&#xff0c;并且通常作为一个单元一起调度和管理。 Pod为容器提供了一个共享的环境&#xff0c;使得容器之间可以方便地通信…

Android进阶之路 - 静态会员进度条

年后这个新版本加入了VIP模块&#xff0c;有幸正好由我来负责&#xff0c;可以再积累一下这方面的知识。 那段时间看了一本书&#xff0c;书中说到初级码农的特性之一就是完全集中于某些功能&#xff0c;忽略了了很多成长机会&#xff0c;所以重复性劳作带来的成长值有限&#…

基于51单片机的智能台灯proteus仿真设计( proteus仿真+程序+原理图+报告+讲解视频)

基于51单片机的红外光敏检测智能台灯控制系统仿真( proteus仿真程序原理图报告讲解视频&#xff09; 1.主要功能&#xff1a; 基于51单片机的红外检测光照检测智能台灯仿真设计 1、检测光照强度并显示在数码管上。 2、具备红外检测人体功能。 3、灯光控制模式分为自动模式…

抓取Google时被屏蔽怎么办?如何避免?

在当今数字化时代&#xff0c;数据采集和网络爬取已成为许多企业和个人必不可少的业务活动。对于爬取搜索引擎数据&#xff0c;特别是Google&#xff0c;使用代理IP是常见的手段。然而&#xff0c;使用代理抓取Google并不是一件轻松的事情&#xff0c;有许多常见的误区可能会导…

vue 语法2

【5】条件渲染和列表渲染 &#xff08;1&#xff09;条件渲染v-if v-else-if v-else 条件渲染根据表达式的真假值来渲染不同的元素或组件。 v-if&#xff1a;当表达式的值为真时&#xff0c;渲染该元素或组件。 v-else-if&#xff1a;当前面的 v-if 或 v-else-if 的表达式为假…

【C++】STL — vector的接口讲解 +详细模拟实现

前言: 本章我们将学习STL中另一个重要的类模板vector… vector是表示可变大小数组的序列容器。就像数组一样&#xff0c;vector也采用的连续存储空间来存储元素。但是又不像数组&#xff0c;它的大小是可以动态改变的本质讲&#xff0c;vector使用动态分配数组来存储它的元素v…

智慧公厕的核心技术详解:物联网、云计算、大数据、自动化控制

公共厕所是城市的重要组成部分&#xff0c;而智慧公厕的建设和管理正成为城市发展的重要方向。智慧公厕的核心技术即是物联网、云计算、大数据和自动化控制。下面将以智慧公厕源头实力厂家广州中期科技有限公司&#xff0c;大量精品案例项目现场实景实图实例&#xff0c;详细介…

Sealos急速部署生产用k8s集群

最近一段时间部署k8s全部使用sealos了&#xff0c;整体使用感觉良好&#xff0c;基本没有什么坑。推荐给大家。 使用 Sealos&#xff0c;可以安装一个不包含任何组件的裸 Kubernetes 集群。 最大的好处是提供 99 年证书&#xff0c;用到我跑路是足够了。不用像之前kubeadm安装…

【计算机科学速成课】笔记一

文章目录 写在前面1.计算机的早期历史2.电子计算机3.布尔运算和逻辑门4.二进制5.算术逻辑单元-ALU6.寄存器和内存 写在前面 所有的一切源于这样一个网站——CS自学指南。 这是新手小白入门计算机科学必要了解的知识——【计算机科学速成课】[40集全/精校] - Crash Course Comp…

地平线的花样年华

北京车展在这个喧闹的“五一”假期落幕了&#xff0c;它留给我们许多思考。 虽然社会面的传播焦点落在了“网红”两个字上&#xff0c;但技术的更新依然如暗流涌动&#xff0c;给这届北京车展写下注脚。整个过程前后&#xff0c;最重要和吸引了最多目光的&#xff0c;是智驾&a…

2024蓝桥杯CTF writeUP--cc

给了个网页&#xff0c;里面有加密算法&#xff0c;密钥&#xff0c;密文 使用在线解码工具 CTF最全在线工具整理_在线ctf工具-CSDN博客 将输出的密文&#xff0c;密钥&#xff0c;vi&#xff0c;加密方式一一对应

Linux变量的认识及环境变量配置详解

文章目录 1、变量的划分2、局部变量3、全局变量4、环境变量4.1、概述4.2、配置临时环境变量4.3、配置永久环境变量4.3.1、用户级配置文件1&#xff09;配置方法一&#xff1a;~/.bashrc文件2&#xff09;配置方法二&#xff1a;~/.profile文件3&#xff09;配置方法三&#xff…

生产制造中刀具管理系统,帮助工厂不再频繁换刀

一、刀具管理的定义与重要性 刀具管理是指对生产过程中使用的各种刀具进行计划、采购、存储、分配、使用、监控、维修和报废等全过程的管理。刀具作为制造过程中的直接工具&#xff0c;其性能、质量和使用效率直接影响产品的加工精度、表面质量和生产效率。因此&#xff0c;建…

ansible—playbook的template、tags、roles模块

目录 一、template 1、简介 2、template模块实例 1.先准备一个以.j2结尾的template模板文件&#xff0c;设置引用的变量&#xff0c;ansible上要先安装httpd 2、修改主机清单文件&#xff0c;使用主机变量定义一个变量名相同而值不同的变量 3、主机添加hosts 4、编写pla…

【漏洞复现】金和OA FileDownLoad接口处存在任意文件读取漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

词袋法TFIDF

Tf-idf⽂本特征提取 TF-IDF的主要思想是&#xff1a;如果某个词或短语在⼀篇⽂章中出现的概率⾼&#xff0c;并且在其他⽂章中很少出现&#xff0c;则认为此词或者短语具有很好的类别区分能⼒&#xff0c;适合⽤来分类。TF-IDF作⽤&#xff1a;⽤以评估⼀字词对于⼀个⽂件集或…
最新文章