单列集合.java

news2024/11/16 3:42:13

单列集合

      为了存储不同类型的多个对象,Java提供了一些特殊系列的类,这些类可以存储任意类型的对象,并且存储的长度可变,这些类统称为集合。可以简单的理解为一个长度可变,可以存储不同数据类型的动态数组。集合都位于java.util包中,使用集合时必须导入java.util包。在学习具体集合之前,先了解一下整个集合的核心继承体系:

单列集合:

双列集合

以上两张图中,红线框里的是接口类型,蓝线框里的是具体的实现类。集合里的核心接口如下表:

集合中的核心接口
        接口                                    描述
Collection

集合中最基本的接口,一般不直接使用该接口

ListCollection的子接口,一般用于存储有序,可重复,有索引的对象,是集合中最常用的接口之一
SetCollection的子接口,一般用于存储无序,不可重复,无索引的对象
Map双列集合的根接口,用于存储一组键值对象,提供键到值的映射

一,Collection接口

Collection接口是单列集合的顶层接口(List,Set使它的子接口),既然是接口就不能直接使用,需要通过实现类!

      它最常见的实现类是ArrayList,LinkedList,HashSet和TreeSet,它定义了各种具体实现类的共性,其他单列集合(实现类)直接或间接的继承该接口。

Collection接口的常用方法
方法声明                                         功能描述
boolean add(Object o)相当前集合中添加一个元素
boolean addAll(Collection c)将指定集合c中的所有元素添加到当前集合中
void clear()清空当前集合中的所有元素
boolean  remove(Object o)删除当前集合中的指定元素
boolean  removeAll(Object c)删除当前集合中包含的集合c的所有元素
boolean  isEmpty()判断当前集合是否为空
boolean  contains(Object o)判断当前集合是否包含某个元素
boolean  containsAll(Collection c)判断当前集合是否包含指定集合c的所有元素
Iterator iterator()返回当前集合的迭代器。迭代器用于遍历集合中的所有元素
int size()获取当前集合的元素个数(集合长度)

1,Collection集合的遍历

     Collection这个系列集合的通用的3种遍历方式:

方法一:Iterator迭代器:

    方法:new出来的集合,调用iterator()方法,创建一个迭代器对象,用来遍历集合。(不同之处是,遍历过程可删除元素)

 public static void main(String[] args) {
        //迭代器循环

//1,创建一个ArrayList集合
        Collection<String> list=new ArrayList<>();
        //向集合中添加元素
        list.add("肘子");
        list.add("大王");
        list.add("晚上好呀");

//2,new出来的集合,调用iterator方法,创建一个迭代器对象,用来遍历集合
        //迭代器就好比是一个箭头,默认指向集合的0索引处
        Iterator<String> iterator = list.iterator();
        //遍历
        while (iterator.hasNext()){  
        //hasNext():判断当前集合中的指针位置是否存有元素(对象),有返回true,没有返回false
            String s = iterator.next();//next():获取元素,并后移指针
            //删除元素
            /*迭代器遍历时,不能用集合中的方法,对元素进行增加或删除
             如果实在要删除,可以用迭代器提供的remove方法进行删除
             如果需要添加,暂时没有方法*/
            if(s.equals("大王")){
                iterator.remove();
            }
            System.out.println(s);
        }
        System.out.println(list);
//迭代器使用完毕,指针不会复位
    }

结果:

📝注意:📝📝📝📝📝📝📝📝📝📝📝📝📝📝📝📝📝📝📝

1,迭代器在遍历集合的时候是不依赖索引的,他是通过创建指针并移动指针的方式,来获取集合中的元素

2,迭代器需要掌握的3个方法:

  • 通过集合的iterator()方法,获取一个迭代器对象(迭代器就好比是一个箭头,默认指向集合的0 索引处);
  • 通过迭代器对象的hasNext()方法,判断当前集合中的指针位置是否存有元素(对象),有返回true,没有返回false;
  • 通过迭代器对象的next()方法获取元素,并后移指针,每一个next()方法都代表一次,获取元素,后移指针,所以一次循环里写一个next()方法。

3,迭代器的四个细节:

  • 如果当前位置没有元素,还要强行获取,会报NoSuchElementException
  • 迭代器遍历完毕,指针不会复位,所以再次遍历,需要重新创建一个迭代器对象
  • 遍历的循环中只能用一次next()方法,因为运行一次指针就后移一位并获取当前指向的对象
  • 迭代器遍历时,不能用集合里的方法进行增加或者删除,只能用迭代器里的方法。

方法二:增强for:

 public static void main(String[] args) {

        //增强for循环
        //创建一个集合
        Collection<String> list=new ArrayList<>();
        //向集合中添加元素
        list.add("肘子");
        list.add("大王");
        list.add("晚上好呀");
        //遍历
        for (String s : list) {
            //s="bbb";//s属于第三方变量,s改变了,但是集合里面的元素不会改变
            System.out.println(s);
            System.out.println(list);
        }
    }

结果:

方法三:Lambda表达式:

public static void main(String[] args) {

        //创建集合
        Collection<String> list=new ArrayList<>();
        //向集合中添加元素
        list.add("肘子");
        list.add("大王");
        list.add("晚上好呀");
        //遍历
        //底层原理:
        //其实也会自己遍历,依次得到每一个元素
        //得到的元素,传递给下面的accept()方法
        //s表示集合中的每一个元素
        list.forEach(new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        });
        System.out.println("------------------");
        //lambda表达式:()->{}
        //():与方法的形参想匹配,数据类型可省略,形参只有一个,小括号可省略
        //{}:与方法体相匹配
        list.forEach(s-> System.out.println(s));//上面forEach()的简化版
    }

结果 :

2,List接口

       List接口继承Collection接口,允许存储重复的元素,所有的元素以线性方式存储。在程序中可以通过索引所有访问List接口实例中存储的元素,且存储的元素是有序的。

       List集合作为Collection集合的子接口,不但继承了Collection接口中的全部方法,而且还增加了根据元素索引操作集合的特有方法。

特点:有序,可重复,有索引

在java.util包可以找到List接口, 它是一个ListIterator接口工厂。通过ListIterator,我们可以向前和向后迭代列表。List接口的实现类是ArrayList、LinkedList、Stack和Vector。ArrayList和LinkedList在Java编程中被广泛使用,Vector类自Java 5以来已弃用。

2.1接口的声明: 

public interface List<E> extends Collection<E> ; 

让我们详细说明如何在List类中创建对象或实例:

  • 因为List是一个接口,所以不能按List类型创建对象。我们总是需要一个实现这个List的类来创建对象(如ArrayList)
  • 在Java 1.5中引入泛型之后,可以限制可以存储在List中的对象的类型, 就像其他几个由用户定义的“类”实现的用户定义的“接口”一样
  • List是一个“接口”,由ArrayList等类实现实现,在java.util 包下

2.2语法: 

List<E> list = new ArrayList<E> (); 
  • E: 泛型数据类型,用于设置 objectName 的数据类型,只能为引用数据类型。添加的元素为基本类型的话,就要使用它的包装类,如下表:
  • list: 创建的集合名

2.3操作: 

现在让我们使用List 接口执行各种操作,以便更好地理解这些操作。我们将讨论下面列出的操作以及稍后通过干净的java代码实现的操作。

由于List是一个接口,它只能与实现该接口的类一起使用。现在,让我们看看如何对List执行一些常用操作。

  • 使用add()方法向List类添加元素
  • 使用set()方法更新List类中的元素
  • 使用get()方法返回元素
  • 使用remove()方法删除元素

现在,让我们分别讨论操作,并在代码中实现相同的操作,以便更好地掌握它。


1.添加操作

为了向列表中添加元素,可以使用add()方法。此方法被重载以基于不同参数执行多个操作。

参数:接受2个参数,分别为:

  • add(Object):该方法用于在List的末尾添加一个元素。
  • add(int index, Object):该方法用于在List的特定索引处添加元素

2. 更新操作

  • 添加元素之后,如果我们希望更改元素,可以使用set(int index,E element)方法来完成。
  • 因为List有索引的,所以我们想要更改的元素会被该元素的索引所引用。
  • 因此,此方法接受一个索引和需要插入到该索引处的更新元素。

3. 返回操作

  • 添加元素之后,如果我们需要得到某个元素,可以使用get(int index)方法来完成。

4. 删除操作

为了从列表中删除一个元素,我们可以使用remove()方法。此方法被重载以基于不同参数执行多个操作

Parameters:

  • remove(Object):该方法用于简单地从List中删除一个对象。如果有多个这样的对象,则删除第一个出现的对象。
  • remove(int index):由于List被建立了索引,所以这个方法接受一个整数值,它只是简单地删除List中特定索引处的元素。删除元素后,所有元素都向左移动以填充空间,并更新对象的索引。

实例: 

public static void main(String[] args) {
        //创建集合E
        List<String> list=new ArrayList<>();


        //添加元素     void add(int index,E element)
        list.add("肘子");
        list.add("大王");
        list.add("晚上好呀");
        list.add("上头的85批");
        System.out.println("原本集合:"+list);

        //删除指定元素  E remove(int index)
        delete(list);

        //修改指定索引元素  E set(int index,E element)
        alter(list);

        //返回指定索引元素  E get(int index)
        obtainE(list);
    }

    private static void delete(List<String> list) {
        System.out.println("删除指定元素---------------");
        //表示删除索引为0的元素
        list.remove(1);
        System.out.println("表示删除索引为0的元素:"+ list);

        //删除第一个元素(手动装箱,手动把基本数据类型肘子,转换成String类型,变成一个对象)
        String i=String.valueOf("大王");
        list.remove(i);
        //为什么相同的remove()方法,运行的效果不同:
        // 在调用方法的时候,如果方法出现了重载,
        // 优先调用型参与实参数据类型相同的那一个
        System.out.println("删除‘大王’元素:"+list);
    }

    private static void alter(List<String> list) {
        System.out.println("替换指定元素--------------------只能替换存在的元素");
        String s1 = list.set(0, "替换索引0");
        System.out.println("返回的是被替换的元素:"+s1); //返回的是被替换的元素
        System.out.println("list集合:"+list);
    }
    private static void obtainE(List<String> list) {
        System.out.println("返回指定索引[0]元素-----------");
        String s = list.get(0);
        System.out.println(s);
        System.out.println("集合list:"+list);
    }

结果: 

2.4 ArrayList

1,概念 🧩

      ArrayList 类是一个实现了List接口的单列集合实现类,可以动态修改的数组,与普通数组的区别就是它是没有固定大小的限制,我们可以添加或删除元素。ArrayList 继承了 AbstractList ,并实现了 List 接口。

2,ArrayList用于🧩

  • 频繁访问列表中的某一个元素
  • 只需要在列表末尾进行添加和删除元素操作
  • 不适合做大量的增删操作,而适合元素的查找 

2.5 LinkedList

1,概念

 java.util.LinkedList是一个实现了List接口的单列集合实现类,底层是一个双向链表,链表中的每一个元素都使用引用的方式记录它的前一个元素和后一个元素,从而将所有的元素连接起来。同时实现了实现了ListDeque接口

优点:🧸🧸🧸

  • 由于LinkedList底层实现是双向链表,所以在进行插入和删除操作方面具有高效性。
  • 由于LinkedList是动态的数据结构,因此在使用时不需要预先分配空间
  • 由于LinkedList实现了Deque接口 在集合的队首和队尾可以进行高效的插入和删除操作

缺点:🧸🧸🧸

  • 由于LinkedList底层实现是双链表,所以从集合中访问某个元素时需要从头开始遍历整个链表,所以其查询操作慢
  • 由于LinkedList在进行元素对象存储时,需要将指向下一个元素和上一个元素的指针同时进行存储,其占用的内存空间相比ArrayList数组要更多。
  • 由于LinkedList是基于链表实现的,因此不支持随机访问,只能通过遍历整个链表来访问元素

 📝📝📝所以, LinkedList 的增加和删除的操作效率更高,而查找和修改的操作效率较低。  

2, LinkedList常用于

  • 你需要通过循环迭代来访问列表中的某些元素。
  • 需要频繁的在列表开头、中间、末尾等位置进行添加和删除元素操作。

3,Set接口

     List接口和Set接口都是Collection的子接口,两者不同的是:Set系列集合添加的元素是无序、不重复、无索引的。

Set系列集合:

  • 无序:存取顺序不一致
  • 不重复:可以去除重复的元素
  • 无索引:没有带索引的方法,所以不能使用普通for循环遍历,也不能通过索引来获取元素

Set集合的实现类:

  • HashSet:无序,不重复,五索引
  • LinkedHashSet:有序,不重复,无索引
  • TreeSet:可排序,不重复,无索引

Set接口中的方法基本与Collection的API一致。没有额外方法去学习,直接使用Collection中常见方法就行。

利用Set系列集合存储字符串并遍历:

package day0606SetDemo;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;
import java.util.function.Consumer;

public class SetDemo1 {
   
    public static void main(String[] args) {
        //1,创建一个Set集合的对象
        Set<String> s=new HashSet<>();
        boolean b = s.add("肘子");
        boolean b2 = s.add("西施");
        boolean b3 = s.add("花木兰r");
        //2,添加元素
        //add()方法的返回值是Boolean类型,对于List来说没有意义,因为它允许元素重复,不管添加什么都返回true,而Set不允许元素重复
        boolean b1 = s.add("肘子");
        System.out.println(b);//true
        System.out.println(b1);//false
        //3,打印集合
        //无序
        System.out.println(s);//[肘子, 花木兰r, 西施]
        //3,1迭代器遍历
        Iterator<String> iterator = s.iterator();
        while (iterator.hasNext()){//判断当前指向的位置是否有元素
            String next = iterator.next();//获取当前元素并指针后移一位
            System.out.println(next);
        }
        System.out.println("-------------------------");
        //3,2增强for
        for (String s1 : s) {
            System.out.println(s1);
        }
        System.out.println("-------------------------");
        //3,3Lambda表达式
        s.forEach( str->System.out.println(str));//str表示集合里的每一个元素
    }
}

注意: 

结果:

1,HashSet 

HashSet底层原理

  • HashSet底层采取哈希表(核心)存储数据
  • 哈希表是一种对于增删改查数据性能都较好的结构 

哈希表组成

  • JDK8之前:数组+链表
  • JDK8开始:数组+链表+红黑树 

哈希值  

        哈希表在底层它是有数组存在的,添加数据,它不是由0索引开始挨个往后添加的,而是根据数组长度和哈希值(公式:int index=(数组长度-1)&哈希值;)计算出元素应该存入数组中哪个位置 

  • 对象的整数表现形式
  • 根据hashCode方法算出来的int类型的整数
  • 该方法定义在Object类中,所有对象都可以调用,默认使用地址值进行计算(意义不是很大)
  • 一般情况下,会重写hashCode方法,利用对象内部的属性值计算哈希值

对象的哈希值特点

  •  如果没有重写hashCode方法,不同对象计算出的哈希值是不同的
  •  如果已经重写hashCode方法,不同对象只有属性值相同,计算出的哈希值就是一样的
  • 小部分情况下,不同的属性值或者不同的地址值计算出的哈希值也有可能一样(哈希碰撞)

重写hashCode方法

右键-->generate-->equals and hashCode-->next-->next-->next-->finish

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Demo2Stu demo2Stu = (Demo2Stu) o;
        return age == demo2Stu.age && Objects.equals(name, demo2Stu.name);
    }

    @Override
    public int hashCode() {
        return Objects.hash(name, age);
    }

🎨总结🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨🎨

HashSet集合的底层数据结构是什么样的?

  • JDK8之前:数组+链表
  • JDK8开始:数组+链表+红黑树 

 底层添加数据原理是什么?

  1. 创建一个默认长度为16,默认加载因子为0.75的数组,数组名为table
  2. 加载因子作用:扩容。当数组存储长度达到16*0.75=12时,数组扩增1倍,数组长度变为32
  3. 如果集合中存储的是自定义对象,则必须要重写hashCode()和equals()方法
  4. 根据公式:int index=(数组长度-1)&哈希值;计算出元素在数组当中应该存入的位置
  5. 判断该位置是否为null,如果是null直接存入
  6. 如果该位置不为null,表是有元素,则调用equals()方法比较属性值
  7. 一样:不存
  8. 不一样:存入数组。JDK8之前:新元素放到数组当中,原本的元素连接到新元素的下面,形成链表。JDK8开始:新元素连接到原本元素的后面,形成链表;
  9. 当链表的长度大于8而且数组长度大于等于64时,链表转成红黑树(JDK8以后)

 HashSet为什么存和取的顺序不一样?

 因为它是从0索引开始,一条链表一条链表开始遍历的。(数组有索引,集合没有)

HashSet为什么没有索引?

  • 因为它是由数组、链表、红黑树3个组合而成的,无法定义索引

HashSet利用什么机制保证数据去重的?

 HashCode方法和equals方法

  • HashCode方法:根据哈希值确定数据添加到哪个位置
  • equals方法:判断要添加的数据与原本该位置上的数据是否重复

2,LinkedHashSet 

 LinkedHashSet集合的特点和原理是什么?

  • 有序、不重复、无索引
  • 底层基于哈希表,但多了一个双向链表记录添加顺序

这个双向链表的目的是存取有序,而不是为了提高增删效率 

以后如果要数据去重,我们使用哪个? 

  • 默认使用HashSet
  • 如果要求去重且存取有序,才使用LinkedHashSet 

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

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

相关文章

mysql的binlog占用大量磁盘空间的解决方法

查看当前日志保存天数&#xff1a; mysql> show variables like %expire_logs_days%; ------------------------- | Variable_name | Value | ------------------------- | expire_logs_days | 0 | ------------------------- 1 row in set (0.08 sec) 默认是0&…

Mac - Node/Java 配置安装全流程

Mac - Node/Java 配置安装全流程 一. Git 安装二. Java 相关安装2.1 jenv 版本控制工具2.2 JDK1.8 和 JDK21的安装2.3 maven 安装 三. Node 相关安装3.1 nvm 版本控制工具3.2 Node 版本安装 一. Git 安装 1.我们首先安装一下Homebrew&#xff0c;这个工具很有用&#xff0c;能…

大数据处理学习笔记

sudo tar -zxvf hadoop-1.1.2.tar.gz -C / #解压到/usr/local目录下 sudo mv hadoop-1.1.2 hadoop #重命名为hadoop sudo chown -R python ./hadoop #修改文件权限 //java安装同上给hadoop配置环境变量&#xff0c;将下面代…

从C到C++,C++入门篇(1)

1.什么是C C是一种通用编程语言&#xff0c;由Bjarne Stroustrup在1980年代初开发&#xff0c;作为C语言的扩展。 C支持多种编程范式&#xff0c;包括过程式编程、数据抽象、面向对象编程和泛型编程等。 这种语言在操作系统、游戏开发、图形界面、嵌入式系统、分布式系统、网…

啵啵啵啵啵啵啵啵啵啵啵啵啵啵啵

欢迎关注博主 Mindtechnist 或加入【智能科技社区】一起学习和分享Linux、C、C、Python、Matlab&#xff0c;机器人运动控制、多机器人协作&#xff0c;智能优化算法&#xff0c;滤波估计、多传感器信息融合&#xff0c;机器学习&#xff0c;人工智能等相关领域的知识和技术。关…

“安全生产月”专题报道:AI智能监控技术如何助力安全生产

今年6月是第23个全国“安全生产月”&#xff0c;6月16日为全国“安全宣传咨询日”。今年全国“安全生产月”活动主题为“人人讲安全、个个会应急——畅通生命通道”。近日&#xff0c;国务院安委会办公室、应急管理部对开展好2024年全国“安全生产月”活动作出安排部署。 随着科…

外贸自动化脚本编写会用到的源代码!

随着全球化的加速推进&#xff0c;外贸行业正迎来前所未有的发展机遇&#xff0c;为了提高工作效率、减少人为错误&#xff0c;并更好地把握市场机遇&#xff0c;越来越多的外贸企业开始关注自动化脚本的编写与应用。 自动化脚本不仅可以帮助企业实现业务流程的自动化&#xf…

python-windows10普通笔记本跑bert mrpc数据样例0.1.001

python-windows10普通笔记本跑bert mrpc数据样例0.1.000 背景参考章节获取数据下载bert模型下载bert代码windows10的cpu执行结果注意事项TODOLIST背景 看了介绍说可以在gpu或者tpu上去微调,当前没环境,所以先在windows10上跑一跑,看是否能顺利进行,目标就是训练的过程中没…

python面向过程与初始面向对象编程

让我们穿越到《龙珠》世界&#xff0c;一起揭开 面向对象编程 的神秘面纱吧。 面向过程编程与面向对象编程 天下第一武道会 选手登记 第 22 届天下第一武道会即将召开&#xff0c;各路武术高手齐聚一堂&#xff0c;其中最受瞩目的&#xff0c;当属卡卡罗特&#xff08;孙悟…

前后端实现文件上传进度条-实时进度

后端接口代码&#xff1a; PostMapping("/upload")public ResponseEntity<String> handleFileUpload(RequestParam("file") MultipartFile file) {try {// 获取文件名String fileName file.getOriginalFilename();// 创建上传目标路径Path targetPa…

CTFHUB-技能树-web-信息泄露

目录 1.目录遍历 2.PHPINFO 3.备份文件下载 3.1 网站源码 3.2 bak文件 3.3 vim缓存 3.4 .DS_Store 4.Git泄露 4.1 Log 4.2 Stash 4.3 Index 5.SVN泄露 6.HG泄露 1.目录遍历 这个没什么好讲的&#xff0c;进去直接点击找flag,然后在下面目录翻&#xff0c;就找到了 …

手撕设计模式——克隆对象之原型模式

1.业务需求 ​ 大家好&#xff0c;我是菠菜啊&#xff0c;前俩天有点忙&#xff0c;今天继续更新了。今天给大家介绍克隆对象——原型模式。老规矩&#xff0c;在介绍这期之前&#xff0c;我们先来看看这样的需求&#xff1a;《西游记》中每次孙悟空拔出一撮猴毛吹一下&#x…

无码高清?Stable DIffusion教程 | 如何利用 Stable Diffusion webui 将图片变得更清晰?全方位对比4种放大方法!

大家好&#xff0c;我是大师兄 1、引言 “高分放大”&#xff08;有时候也叫“超分放大”或“高清修复”&#xff09;描述了在确保图像清晰度的前提下提升图片分辨率的过程。例如&#xff0c;将一张512 x 512的图片放大四倍&#xff0c;得到的就是2048 x 2048分辨率的图片&am…

现代社区管理中的电瓶车违停检测技术

随着城市化进程的加快&#xff0c;电瓶车作为一种环保、便捷的出行工具在社区内的使用越来越普及。然而&#xff0c;电瓶车的随意停放问题也日益严重&#xff0c;影响了社区的整体环境和居民的生活质量。为了解决这一问题&#xff0c;社区管理者迫切需要一种高效、准确的电瓶车…

Qt:QDialogButtonBox的使用

QDialogButtonBox是Qt自带的按钮箱&#xff0c;通过枚举QDialogButtonBox::ButtonRole可以添加Qt定义按钮&#xff0c;或者通过方法QDialogButtonBox::addButton添加自定义的按钮。 // 自定义按钮。 button_box_ new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonB…

【Python报错】已解决SyntaxError: invalid character in identifier

成功解决“SyntaxError: invalid character in identifier”错误的全面指南 一、引言 在Python编程中&#xff0c;SyntaxError是一种常见的编程错误&#xff0c;它表明Python解释器在解析代码时遇到了不符合语法规则的情况。其中&#xff0c;“SyntaxError: invalid character…

vue3_组件间通信方式

目录 一、父子通信 1.父传子&#xff08; defineProps&#xff09; 2.父传子&#xff08;useAttrs&#xff09; 3.子传父&#xff08;ref&#xff0c;defineExpose &#xff09; 4.子传父&#xff08;defineEmits&#xff09; 5.子传父&#xff08;v-model&#xff09; …

OSI协议集

国际标准化组织除了定义osi参考模型之外&#xff0c;还开发了实现7个功能层次的各种协议和服务标准&#xff0c;这些协议和服务统称为osi协议。osi协议是一些已有的协议和iso新开发的协议的混合体&#xff0c;例如&#xff0c;大部分物理层和数据链路层协议是采用现有的协议&am…

数组中的第K个最大元素 ---- 分治-快排

题目链接 题目: 分析: 这道题很明显是一个top-K问题, 我们很容易想到用堆排序来解决, 堆排序的时间复杂度是O(N*logN), 不符合题意, 所以我们可以用另一种方法:快速选择算法, 他的时间复杂度为O(N)快速选择算法, 其实是基于快排, 进行修改而成, 我们还是使用将"将数组分…

QT treeWidget如何添加虚线

1、添加以下代码即可&#xff1a; ui.treeWidget->setStyle(QStyleFactory::create("windows"));2、效果如下&#xff1a;