【Java数据结构 -- List和ArrayList与顺序表】

List和ArrayList与顺序表

  • 一. List
    • 1.1 List介绍
    • 2.1 常见接口介绍
    • 3.1 List的使用
  • 二. ArrayList与顺序表
    • 1.线性表
    • 2.顺序表
      • 2.1 接口的实现
    • 3.ArrayList简介
    • 4. ArrayList使用
      • 4.1 ArrayList的构造
    • 4.2 ArrayList常见操作
    • 4.3 ArrayList的遍历
    • 4.4 ArrayList的扩容机制
    • 5. ArrayList的具体使用
      • 5.1 简单的洗牌算法
      • 5.2 杨辉三角的实现
    • 6 面试题

一. List

1.1 List介绍

在集合框架中,List是一个接口,继承Collection
Iterable <-- Collection <-- List

Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示:
在这里插入图片描述
Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下:
在这里插入图片描述
站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作

2.1 常见接口介绍

List中提供了很多方法,具体的常用方法如下:
方法 ---- 解释
boolean add(E e) ---- 尾插 e
void add(int index, E element) ---- 将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c) ---- 尾插 c 中的元素
E remove(int index) ---- 删除 index 位置元素
boolean remove(Object o) ---- 删除遇到的第一个 o
E get(int index) ---- 获取下标 index 位置元素
E set(int index, E element) ---- 将下标 index 位置元素设置为 element
void clear() ---- 清空
boolean contains(Object o) ---- 判断 o 是否在线性表中
int indexOf(Object o) ---- 返回第一个 o 所在下标
int lastIndexOf(Object o) ---- 返回最后一个 o 的下标
List subList(int fromIndex, int toIndex) ---- 截取部分 list

3.1 List的使用

List是一个接口,并不是直接用来实例化
如果要使用的话必须先去实例化List的实现类,ArrayLsit和LinkedList都实现了List接口。

二. ArrayList与顺序表

1.线性表

线性表是n个具有相同特性的数据元素的有限序列。线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列等等。

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储
在这里插入图片描述

2.顺序表

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

2.1 接口的实现

IList接口:

public interface IList {
    // 新增元素,默认在数组最后新增
    public void add(int data);
    // 在 pos 位置新增元素
    public void add(int pos, int data);
    // 判定是否包含某个元素
    public boolean contains(int toFind);
    // 查找某个元素对应的位置
    public int indexOf(int toFind);
    // 获取 pos 位置的元素
    public int get(int pos);
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value);
    //删除第一次出现的关键字key
    public void remove(int toRemove);
    // 获取顺序表长度
    public int size();
    // 清空顺序表
    public void clear();
    // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
    public void display();

    Boolean isFull();
    Boolean isEmpty();
}

实现ArrayList方法:

public class MyArrayList implements IList{
    public int[] elem;
    public int usedSize;
    public static final int DEFAULT_CAPACITY = 5;

    public MyArrayList() {
        elem = new int[DEFAULT_CAPACITY];
    }

    @Override
    public void display() {
        for (int i = 0; i < this.usedSize; i++) {
            System.out.println(elem[i]+" ");
        }
        System.out.println();
    }

    @Override
    public void add(int data) {
        // 判断是否满了 满了就要扩容
        if (isFull()) {
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        this.elem[usedSize] = data;
        this.usedSize++;
    }

    @Override
    public Boolean isFull() {
        return this.usedSize == DEFAULT_CAPACITY;
    }

    @Override
    public void add(int pos, int data) {
        // pos位置的判断
        checkPosOfAdd(pos);
        if (isFull()) {
            elem = Arrays.copyOf(elem,elem.length*2);
        }
        for (int i = this.usedSize-1; i >= pos; i--) {
            this.elem[i+1] = elem[i];
        }
        this.elem[pos] = data;
        this.usedSize++;

        System.out.println();
    }

    private void checkPosOfAdd(int pos) {
        if (pos<0 || pos >this.usedSize) {
            throw new PosException("Pos位置为:"+ pos);
        }
    }

    @Override
    public boolean contains(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (elem[i] == toFind){
                return true;
            }
        }
        return false;
    }

    @Override
    public int indexOf(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    // 获取pos位置的值
    @Override
    public int get(int pos) {
        // 判断pos位置
        checkPosOfGet(pos);

        // 为空
        if (isEmpty()) {
            throw new EmptyException("顺序表为空");
            //return -1;
        }
        return this.elem[pos];
    }

    public Boolean isEmpty() {
        return usedSize ==0;
    }


    private void checkPosOfGet(int pos){
        if (pos < 0 || pos >= this.usedSize) {
            throw new PosException("Pos位置不合法:"+pos);
        }
    }


    // 更新pos位置的值为value
    @Override
    public void set(int pos, int value) {
        checkPosOfGet(pos);
        if (isEmpty()) {
            System.out.println("顺序表为空");
        }
        this.elem[pos] = value;
    }

    // 删除toRemove这个值
    @Override
    public void remove(int toRemove) {
        if (isEmpty()) {
            throw new EmptyException("顺序表为空");
        }
        int index=indexOf(toRemove);
        for (int i = index; i < this.usedSize-1; i++) {
            this.elem[i] = this.elem[i+1];
        }
        this.usedSize--;
    }

    @Override
    public int size() {
        return this.usedSize;
    }

    //清空顺序表  防止数据泄露
    @Override
    public void clear() {
        this.usedSize = 0;
    }
}

注意

  • 在定义了一个空顺序表的时候第一次add分配了默认的内存大小
  • 在扩容的时候是以1.5倍扩容
    Main测试:

    public static void main2(String[] args) {
/*        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);

        arrayList.add(0,99);*/
        //第一次add的时候  分配了内存大小为10
        //扩容的时候 是1.5倍扩容


        ArrayList<Integer> arrayList1 = new ArrayList<>();
        arrayList1.add(10);
        arrayList1.add(20);
        arrayList1.add(30);

        // 传入的参数是E类型或者是E类型的子类
        ArrayList<Number> arrayList2 = new ArrayList<>(arrayList1);
        arrayList2.add(9999);
        System.out.println(arrayList2);
        //[10, 20, 30, 9999]

        //list 通过sublist截取后 指向的还是arrayList2所指向的内容 即list和arrayList2指向的内容一致
        // 所以修改list指向的内容就是 arrayList2的值也会变
        List<Number> list = arrayList2.subList(0,2);
        System.out.println(list);
        //[10, 20]

        System.out.println("=====");
        list.set(0,199);

        System.out.println(arrayList2);  //[199, 20, 30, 9999]
        System.out.println(list);       //[199, 20]



    }
    public static void main1(String[] args) {
        MyArrayList myArrayList = new MyArrayList();
        myArrayList.add(1);
        myArrayList.add(2);
        myArrayList.add(3);
        myArrayList.add(4);
        myArrayList.add(5);
        myArrayList.add(6);

        System.out.println(myArrayList.contains(3));
        System.out.println(myArrayList.indexOf(5));

        myArrayList.remove(3);
        myArrayList.display();
    }

3.ArrayList简介

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架图如下:
在这里插入图片描述注意:

  1. ArrayList是以泛型方式实现的,使用时必须要先实例化
  2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
  4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的
  5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者CopyOnWriteArrayList
  6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

4. ArrayList使用

4.1 ArrayList的构造

在这里插入图片描述
注意在这里的extends E 传入的是E类型或者是E的子类型

public static void main(String[] args) {
	// ArrayList创建,推荐写法
	// 构造一个空的列表
	List<Integer> list1 = new ArrayList<>();
	// 构造一个具有10个容量的列表
	List<Integer> list2 = new ArrayList<>(10);
	list2.add(1);
	list2.add(2);
	list2.add(3);
	// list2.add("hello"); // 编译失败,List<Integer>已经限定了,list2中只能存储整形元素
	// list3构造好之后,与list中的元素一致
	ArrayList<Integer> list3 = new ArrayList<>(list2);
	// 避免省略类型,否则:任意类型的元素都可以存放,使用时将是一场灾难
	List list4 = new ArrayList();
	list4.add("111");
	list4.add(100);
}

4.2 ArrayList常见操作

方法 ------ 解释
boolean add(E e) ------ 尾插 e
void add(int index, E element) ------ 将 e 插入到 index 位置
boolean addAll(Collection<? extends E> c) ------ 尾插 c 中的元素
E remove(int index) ------ 删除 index 位置元素
boolean remove(Object o) ------ 删除遇到的第一个 o
E get(int index) ------ 获取下标 index 位置元素
E set(int index, E element) ------ 将下标 index 位置元素设置为 element
void clear() ------ 清空
boolean contains(Object o) ------ 判断 o 是否在线性表中
int indexOf(Object o) ------ 返回第一个 o 所在下标
int lastIndexOf(Object o) ------ 返回最后一个 o 的下标
List subList(int fromIndex, int toIndex) ------ 截取部分 list

    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("JavaSE");
        list.add("JavaWeb");
        list.add("JavaEE");
        list.add("JVM");
        list.add("测试课程");
        System.out.println(list);

        // 获取list中有效元素个数
        System.out.println(list.size());

        // 获取和设置index位置上的元素,注意index必须介于[0, size)间
        System.out.println(list.get(1));

        list.set(1, "JavaWEB");
        System.out.println(list.get(1));

        // 在list的index位置插入指定元素,index及后续的元素统一往后搬移一个位置
        list.add(1, "Java数据结构");
        System.out.println(list);

        // 删除指定元素,找到了就删除,该元素之后的元素统一往前搬移一个位置
        list.remove("JVM");
        System.out.println(list);

        // 删除list中index位置上的元素,注意index不要超过list中有效元素个数,否则会抛出下标越界异常
        list.remove(list.size()-1);
        System.out.println(list);

        // 检测list中是否包含指定元素,包含返回true,否则返回false
        if(list.contains("测试课程")){
            list.add("测试课程");
        }

        // 查找指定元素第一次出现的位置:indexOf从前往后找,lastIndexOf从后往前找
        list.add("JavaSE");
        System.out.println(list.indexOf("JavaSE"));
        System.out.println(list.lastIndexOf("JavaSE"));

        // 使用list中[0, 4)之间的元素构成一个新的SubList返回,但是和ArrayList共用一个elementData数组
        List<String> ret = list.subList(0, 4);
        System.out.println(ret);

        list.clear();
        System.out.println(list.size());
    }

4.3 ArrayList的遍历

ArrayList 可以使用三方方式遍历:for循环+下标、foreach、使用迭代器

    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(10);
        arrayList.add(20);
        arrayList.add(30);

        //ArrayList的遍历
        //第一种遍历方式   重写了toString方法
        System.out.println(arrayList);

        //第二种遍历方式
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i)+" ");
        }

        System.out.println();

        //3.for-each
        for (int x:arrayList) {
            System.out.print(x+" ");
        }
        System.out.println();

        // 4. 迭代器
        Iterator<Integer> it = arrayList.iterator();
        while (it.hasNext()) {
            System.out.print(it.next()+" ");
        }
        System.out.println();

        //5. ListIterator  是 Iterator的子类
        ListIterator<Integer> it2 = arrayList.listIterator();
        while (it2.hasNext()) {
            System.out.print(it2.next()+" ");
        }
        System.out.println();

        //6. 从后往前打印
        ListIterator<Integer> it3 = arrayList.listIterator();
        while (it2.hasPrevious()) {
            System.out.print(it2.previous()+" ");
        }
        System.out.println();
    }

4.4 ArrayList的扩容机制

ArrayList是一个动态类型的顺序表,即:在插入元素的过程中会自动扩容。
ArrayList源码:

Object[] elementData; // 存放元素的空间
private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {}; // 默认空间
private static final int DEFAULT_CAPACITY = 10; // 默认容量大小
public boolean add(E e) {
	ensureCapacityInternal(size + 1); // Increments modCount!!
	elementData[size++] = e;
	return true;
}
private void ensureCapacityInternal(int minCapacity) {
	ensureExplicitCapacity(calculateCapacity(elementData, minCapacity));
}
private static int calculateCapacity(Object[] elementData, int minCapacity) {
	if (elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
	return Math.max(DEFAULT_CAPACITY, minCapacity);
	}
	return minCapacity;
}
private void ensureExplicitCapacity(int minCapacity) {
	modCount++;
	// overflow-conscious code
	if (minCapacity - elementData.length > 0)
	grow(minCapacity);
}
private static final int MAX_ARRAY_SIZE = Integer.MAX_VALUE - 8;
private void grow(int minCapacity) {
	// 获取旧空间大小
	int oldCapacity = elementData.length;
	// 预计按照1.5倍方式扩容
	int newCapacity = oldCapacity + (oldCapacity >> 1);
	// 如果用户需要扩容大小 超过 原空间1.5倍,按照用户所需大小扩容
	if (newCapacity - minCapacity < 0)
	newCapacity = minCapacity;
	// 如果需要扩容大小超过MAX_ARRAY_SIZE,重新计算容量大小
	if (newCapacity - MAX_ARRAY_SIZE > 0)
	newCapacity = hugeCapacity(minCapacity);
	// 调用copyOf扩容
	elementData = Arrays.copyOf(elementData, newCapacity);
}
private static int hugeCapacity(int minCapacity) {
	// 如果minCapacity小于0,抛出OutOfMemoryError异常
	if (minCapacity < 0)
	throw new OutOfMemoryError();
	return (minCapacity > MAX_ARRAY_SIZE) ? Integer.MAX_VALUE : MAX_ARRAY_SIZE;
}

总结:

  1. 检测是否真正需要扩容,如果是调用grow准备扩容
  2. 预估需要库容的大小初步预估按照1.5倍大小扩容,如果用户所需大小超过预估1.5倍大小,则按照用户所需大小扩容,真正扩容之前检测是否能扩容成功,防止太大导致扩容失败
  3. 使用copyOf进行扩容

5. ArrayList的具体使用

5.1 简单的洗牌算法

Card:

public class Card {
    public String suit;
    public int num;

    public Card(String suit, int num) {
        this.suit = suit;
        this.num = num;
    }

    @Override
    public String toString() {
        /*return "Card{" +
                "suit='" + suit + '\'' +
                ", num=" + num +
                '}';*/
        return suit +""+num;
    }
}

Cardgame:

import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class Cardgame {
    public static final String[] suits = {"♥","♣","♦","♠"};

    // 买牌 (创建牌)
    public List<Card> buyCard() {
        List<Card> cardList = new ArrayList<>();
        for (int i = 0; i < 4; i++) {
            for (int j = 0; j < 13; j++) {
                cardList.add(new Card(suits[i],j));//相当于下面代码
                /*String suit = suits[i];
                Card card = new Card(suit,j)
                cardList.add(card);*/
            }
        }
        return cardList;
    }

    // 洗牌
    public void shuffle(List<Card> cardList) {
        Random random = new Random();
        for (int i = cardList.size()-1; i > 0; i--) {
            int index = random.nextInt(i);

            swap(cardList,i,index);
        }
    }

    private static void swap(List<Card> cardList,int i,int j) {
        Card tmp = cardList.get(i);
        cardList.set(i,cardList.get(j));
        cardList.set(j,tmp);
    }

    // 发牌 3个人每个人轮流抓5张牌
    // 思路:1.每个人拿到牌 放到哪
    //      2. l轮流怎么抓5张牌

    public List<List<Card>> getCard(List<Card> cardList) {
        List<Card> hand1 = new ArrayList<>();
        List<Card> hand2 = new ArrayList<>();
        List<Card> hand3 = new ArrayList<>();

        List<List<Card>> hand = new ArrayList<>();
        hand.add(hand1);
        hand.add(hand2);
        hand.add(hand3);

        for (int i = 0; i < 5; i++) {  // 拿五次牌
            for (int j = 0; j < 3; j++) {  // 3个人
                //怎么揭牌?  每次相当于 删除下0标这个牌
                Card card = cardList.remove(0);
                // 怎么放到对应人的手里面?
                hand.get(j).add(card);
            }
        }
        return hand;
    }
}

Main测试:

import java.util.List;

public class Main {
    public static void main(String[] args) {
        Cardgame cardgame = new Cardgame();
        List<Card> ret = cardgame.buyCard();
        System.out.println("买牌:");
        System.out.println(ret);

        cardgame.shuffle(ret);
        System.out.println("洗牌:");
        System.out.println(ret);

        System.out.println("揭牌:");
        List<List<Card>> hand = cardgame.getCard(ret);
        for (int i = 0; i < hand.size(); i++) {
            System.out.println("第"+(i+1)+"个人的牌"+hand.get(i));
        }
        System.out.println("剩下的牌");
        System.out.println(ret);
    }

}

在这里插入图片描述

5.2 杨辉三角的实现

具体要求:
在这里插入图片描述

    public List<List<Integer>> generate(int numRows) {
        // 定义一个二维数组
        List<List<Integer>> ret = new ArrayList<>();

        List<Integer> list = new ArrayList<>();
        list.add(1);

        ret.add(list);

        for (int i = 1; i < numRows; i++) {
            //每循环一次  就是一行
            List<Integer> curRow = new ArrayList<>();
            curRow.add(1);  //每行的第一个元素

            //处理中间的数字
            List<Integer> preRow = ret.get(i-1);
            for (int j = 1; j < i; j++) {
                int x = preRow.get(j)+preRow.get(j-1);
                curRow.add(x);
            }

            //处理最后一个数字
            curRow.add(1);

            ret.add(curRow);
        }
        return ret;
    }

6 面试题

CVTE面试题:
str1:“welcome to cvte”
str2: “come”
删除字符串1当中,出现的所有字符串2当中的字符, 即结果为 “wl t vt”

public class Test {
    public static List<Character> func(String str1,String str2) {
        List<Character> list = new ArrayList<>();
        for (int i = 0; i < str1.length(); i++) {
            char ch = str1.charAt(i);
            if(!str2.contains(ch+"")) { //contains接收的是字符串  所以字符ch +""
                list.add(ch);
            }
        }
        return list;
    }
    public static void main(String[] args) {
        List<Character> ret = func("welcome to cvte","come");
        for (Character ch:ret) {
            System.out.print(ch);
        }
    }
}

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

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

相关文章

HarmonyOS 振动效果开发指导

Vibrator 开发概述 振动器模块服务最大化开放硬工最新马达器件能力&#xff0c;通过拓展原生马达服务实现振动与交互融合设计&#xff0c;打造细腻精致的一体化振动体验和差异化体验&#xff0c;提升用户交互效率和易用性、提升用户体验、增强品牌竞争力。 运作机制 Vibrato…

排序:快速排序(hoare版本)

目录 快速排序&#xff1a; 概念&#xff1a; 动画分析&#xff1a; 代码实现&#xff1a; 代码分析&#xff1a; 代码特性&#xff1a; 常见问题&#xff1a; 快速排序&#xff1a; 概念&#xff1a; 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法&a…

ESP32-Web-Server编程- 在 Web 上开发动态纪念册

ESP32-Web-Server编程- 在 Web 上开发动态纪念册 概述 Web 有很多有趣的玩法&#xff0c;在打开网页的同时送她一个惊喜。 需求及功能解析 本节演示在 ESP32 上部署一个 Web&#xff0c;当打开对应的网页时&#xff0c;将运行动态的网页内容&#xff0c;显示炫酷的纪念贺词…

对Spring源码的学习:二

目录 SpringBean实例化流程 Spring的后处理器 Bean工厂后处理器 SpringBean实例化流程 Spring容器在进行初始化时&#xff0c;会将xml配置的<bean>的信息封装成一个BeanDefinition对象&#xff0c;所有的BeanDefinition存储到一个名为beanDefinitionMap的Map集合中去…

2023.12.6 关于 Spring Boot 事务的基本概念

目录 事务基本概念 前置准备 Spring Boot 事务使用 编程式事务 声明式事务 Transactional 注解参数说明 Transational 对异常的处理 解决方案一 解决方案二 Transactional 的工作原理 面试题 Spring Boot 事务失效的场景有那些&#xff1f; 事务基本概念 事务指一…

基于深度学习的遥感图像变化差异可视化系统

1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 研究背景与意义 遥感图像变化差异可视化是遥感图像处理和分析的重要研究领域之一。随着遥感技术的快速发展和遥感数据的广泛应用&#xff0c;遥感图像的获取和处理变得越来越容易…

Javaweb | Servlet编程

目录: 1.认识Servlet2.编写Servlet3.Servlet的运行机制4.Servlet的生命周期4.1 Servlet生命周期图init()方法doGet()doPost()service()destroy()方法 5.解决“控制台”打印中文乱码问题6.Servlet 和 JSP内置对象 (常用对象)获得out对象获得request 和 response对象获得session对…

KeePass开源密码管理器

KeePass开源密码管理器 KeePass 是一款免费的开源密码管理器&#xff0c;KeePass 将密码存储为一个数据库&#xff0c;而这个数据库由一个主密码或密码文件锁住&#xff0c;也就是说我们只需要记住一个主密码&#xff0c;或使用一个密码文件&#xff0c;就可以解开这个数据库&a…

每日一题:LeetCode-11.盛水最多的容器

每日一题系列&#xff08;day 13&#xff09; 前言&#xff1a; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f308; &#x1f50e…

服务器安装JDK17 版本显示JDK8

服务器之前安装的是JDK8&#xff0c;后面升级JDK17后&#xff0c;发现执行 java -vsrsion 显示的是此时我的环境变量已经换成了JAVA17的路径 输入&#xff1a; vim /etc/profile 解决办法&#xff1a; 1.更新自己环境变量 bash export JAVA_HOME/usr/local/jdk-17.0.7 …

【科普】什么是电子印章? PS抠的印章能用吗?

各类扣章教程一搜一大堆&#xff0c;说明大家对于电子印章使用需求很高。不过要谨记&#xff0c;不要随便抠印章用于公文、证明书、合同协议、收据发票等电子文件&#xff0c;否则可能会吃牢饭。 单是一张电子化的图片是不具备合法性的。那有的人就要问了&#xff0c;我见到的…

读书笔记-《数据结构与算法》-摘要4[插入排序]

插入排序 核心&#xff1a;通过构建有序序列&#xff0c;对于未排序序列&#xff0c;在已排序序列中从后向前扫描(对于单向链表则只能从前往后遍历)&#xff0c;找到相应位置并插入。实现上通常使用in-place排序(需用到O(1)的额外空间) 从第一个元素开始&#xff0c;该元素可…

【微服务】springboot整合quartz使用详解

目录 一、前言 二、quartz介绍 2.1 quartz概述 2.2 quartz优缺点 2.3 quartz核心概念 2.3.1 Scheduler 2.3.2 Trigger 2.3.3 Job 2.3.4 JobDetail 2.4 Quartz作业存储类型 2.5 适用场景 三、Cron表达式 3.1 Cron表达式语法 3.2 Cron表达式各元素说明 3.3 Cron表达…

封装PoiExcelUtils

作者简介&#xff1a;大家好&#xff0c;我是smart哥&#xff0c;前中兴通讯、美团架构师&#xff0c;现某互联网公司CTO 联系qq&#xff1a;184480602&#xff0c;加我进群&#xff0c;大家一起学习&#xff0c;一起进步&#xff0c;一起对抗互联网寒冬 为什么要封装PoiExcelU…

Openfire CVE-2023-32315(metasploit版)

step1&#xff1a;用docker搭建环境 Step2&#xff1a;docker查看映射端口 Step3&#xff1a;打开mysql和apache2&#xff0c;访问特定端口&#xff0c;然后靶标应用。 Step4&#xff1a;用metasploit进行攻击&#xff1a; 首先&#xff0c;打开metasploit&#xff0c;然…

Java (JDK 21) 调用 OpenCV (4.8.0)

Java 调用 OpenCV 一.OpenCV 下载和安装二.创建 Java Maven 项目三.其他测试 一.OpenCV 下载和安装 Open CV 官网 可以下载编译好的包&#xff0c;也可以下载源码自行编译 双击安装 opencv-4.8.0-windows.exe 默认为当前目录 安装即解压缩 根据系统位数选择 将 x64 目录下 op…

数据结构 | 查漏补缺之求叶子结点,分离链接法、最小生成树、DFS、BFS

求叶子结点的个数 参考博文&#xff1a; 树中的叶子结点的个数 计算方法_求树的叶子节点个数-CSDN博客 分离链接法 参考博文 数据结构和算法——哈希查找冲突处理方法&#xff08;开放地址法-线性探测、平方探测、双散列探测、再散列&#xff0c;分离链接法&#xff09;_线性…

Linux存储软件栈到底有多复杂,存储软件栈全景概览

从今天开始&#xff0c;我们将介绍一下Linux的存储软件栈&#xff0c;也称为IO栈。今天我们先从整体上了解一下Linux的整个IO栈&#xff0c;后续再深入介绍每个组件。我们很难说清楚Linux的存储软件栈到底有多复杂&#xff0c;但thomas-krenn的一张图可能可以给大家一个比较直观…

堆的相关时间复杂度计算(C语言)

目录 前言 建堆的时间复杂度 向上调整建堆的时间复杂度 向下调整建堆的时间复杂度 维护堆的时间复杂度 top K问题的时间复杂度 前言 在前面的三篇文章中我们成功的实现了堆排序的升降序以及基于堆的top K问题&#xff0c;现在我们来解决它们的时间复杂度问题 建堆的时间…

查看Linux的Ubuntu的版本

我的Ubuntu版本是 Jammy x86_64&#xff0c;即 Ubuntu 22.04.3 LTS&#xff0c;代号为"Jammy Jellyfish"&#xff0c;架构是 x86_64&#xff08;64位&#xff09;。
最新文章