Java算法和集合

news2024/11/14 5:57:20

1. 排序

1.1. 排序概述

在这里插入图片描述

1.2. 冒泡排序

  1. 整个数列分成两部分:前面是无序数列,后面是有序数列
  2. 初始状态,整个数列都是无序的,有序数列为空
  3. 如果一个数列有n个元素,至多需要n-1趟循环才能保证数列有序
  4. 每一趟循环可以让无序数列中最大数排到最后
  5. 每一趟循环都从数列的第一个元素开始比较,依次比较相邻的两个元素,比较到无序数列的末尾为止
  6. 如果前一个大于后一个,交换
    在这里插入图片描述
public class TestBubbleSort1 {
    public static void main(String[] args) {
        int [] arr = {75,87,56,45,89,100,76,34,89,97};
        // n个元素排序,最多比较n-1次
        for (int i = 0; i < arr.length - 1; i++) {
            // 假设有序
            boolean flag = true;
            for (int j = 0; j < arr.length - 1 -i; j++) {
                // 前一个比后一个大
                if(arr[j] > arr[j + 1]) {
                    int temp = arr[j];
                    arr[j] = arr[j + 1];
                    arr[j + 1] = temp;
                    // 发生交换了,数组无序
                    flag = false;
                }
            }
            // 有序,直接退出循环
            if(flag) break;
        }
        System.out.println(Arrays.toString(arr)); // [34, 45, 56, 75, 76, 87, 89, 89, 97, 100]
    }
}

1.3. 选择排序

  1. 整个数列分成两部分:前面是有序数列,后面是无序数列
  2. 初始状态下,整个数列都是无序的,有序数列为空
  3. 一共n个数,需要n-1趟循环
  4. 每比较完一趟,有序数量+1,无序数量-1
  5. 每趟假设无序数列的第1个元素(整个数列的第i个元素)是最小的,从第i+1个元素开始比较,直到最后一个元素,如果找到更小的数,则假设找到的这个数就是最小数
  6. 一趟比较结束后,将发现最小数,和无序数列的第一个数交换
    在这里插入图片描述
public class TestSelectSort {
    public static void main(String[] args) {
        int [] scoreArr = {75,87,56,45,89,100,76,34,89,97};
        // scoreArr.length个元素排序,需要比较scoreArr.length-1趟
        for (int i = 0; i < scoreArr.length - 1; i++) {
            // 第i趟,假设第i个最小
            int minIndex = i;
            // 从第i+1个数开始比较,使用第i和每个数相比较,比到最后
            for (int j = i + 1; j < scoreArr.length; j++) {
                // 找到了更小的数,更新第i个的最小值
                if(scoreArr[minIndex] > scoreArr[j]) {
                    minIndex = j;
                }
            }
            // 一趟比较完成后,如果最小值的索引改变了,则交换
            if(minIndex != i) {
                int temp = scoreArr[i];
                scoreArr[i] = scoreArr[minIndex];
                scoreArr[minIndex] = temp;
            }
        }
        System.out.println(Arrays.toString(scoreArr)); // [34, 45, 56, 75, 76, 87, 89, 89, 97, 100]
    }
}
  • 注意
    • 冒泡排序最多比较n-1趟循环,最少1趟;选择排序必须比较n-1趟循环
    • 冒泡排序中最多的操作就是比较和交换,一趟循环中可能发生多次交换;选择排序中最多的操作是比较,一趟比较结束后发现更小的值才交换
    • 如果数组元素不是基本数据类型,而是对象,进行比较时,让相应的类实现Comparable接口并调用compareTo()方法进行比较
    • 快速排序是冒泡排序的完整版,都是基于交换排序的,是基于比较的排序算法中效率最高的,用到了分治和递归的思想

2. 递归和折半查找

2.1. 递归

2.1.1. 阶乘

public class TestRecursion1 {
    public static void main(String[] args) {
        int n = 6;
        int result = fac(n);
        System.out.println(result); // 720
    }
    public static int fac(int n) {
        int result;
        if(n == 1) result = 1;
        else result = n * fac(n - 1);
        return result;
    }
}

2.1.2. 斐波那契数列

F(1) = 1, F(2) = 1, F(n) = F(n - 1) + F(n - 2)

public class TestRecursion2 {
    public static void main(String[] args) {
        int n = 40;
        int result = fibo(n);
        System.out.println(result); // 102334155
    }
    public static int fibo(int n) {
        int result = 0;
        if(n == 1 || n == 2) result = 1;
        else result = fibo(n - 1) + fibo(n - 2);
        return result;
    }
}
  • 递归的缺点
    • 占用大量系统堆栈,耗内存
    • 调用层次过多速度比循环慢得多

2.2. 折半查找

折半查找又称二分查找,使用折半查找的查找表必须使用顺序存储结构且按关键字大小有序排列

  • key = 21的查找过程
    在这里插入图片描述
  • key = 85的查找过程
    在这里插入图片描述

2.2.1. 非递归方式

public class BinarySearch {
    public static void main(String[] args) {
        int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
        System.out.println(searchLoop(array, 8)); // 7
    }
    public static int searchLoop(int[] array, int findValue) {
        if(array == null) return -1;
        int start = 0;
        int end = array.length - 1;
        while(start <= end) {
            // 中间位置
            int middle = (start + end) / 2;
            // 中间值
            int middleValue = array[middle];
            if(findValue == middleValue) return middle;
            // 小于中间值,在中间位置前面找
            else if(findValue < middleValue) end = middle - 1;
            // 大于中间值,在中间位置后面找
            else start = middle + 1;
        }
        // 没有找到,返回-1
        return -1;
    }
}

2.2.2. 递归方式

public class BinarySearch2 {
    public static void main(String[] args) {
        int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
        System.out.println(binSearch(array, 8)); // 7
    }
    public static int binSearch(int[] array, int key) {
        int start = 0;
        int end = array.length - 1;
        return binSearch(array, start, end, key);
    }
    public static int binSearch(int[] array, int start, int end, int key) {
        int mid = (start + end) / 2;
        if(start > end) return -1;
        if(array[mid] == key) return mid;
        else if(key > array[mid]) return binSearch(array, mid + 1, end, key);
        else return binSearch(array, start, mid - 1, key);
    }
}

3. 集合引入和ArrayList

3.1. 引入集合

3.1.1. 集合和数组比较

  • 相同点:都可以存储多个对象,对外作为一个整体存在
  • 数组的缺点
    • 长度必须在初始化时确定,且固定不可变
    • 采用连续的存储空间,删除和添加效率低
    • 无法直接保存映射关系
    • 缺乏封装,操作繁琐

3.1.2. 集合框架

java集合框架提供了一套性能优良、使用方便的接口和类,位于java.util包中。存放在集合中的数据,被称为元素
在这里插入图片描述
在这里插入图片描述

  • 集合架构
    • Collection接口存储一组不唯一、无序的对象
    • List接口存储一组不唯一、有序(索引顺序)的对象
    • Set接口存储一组唯一、无序的对象
    • Map接口存储一组键值对象提供key到value的映射
      • key唯一、无序
      • value不唯一、无序

3.1.3. List的主要实现类

  • List
    • 特点:有序,不唯一(可重复)
  • ArrayList
    • 在内存中分配连续的空间,实现了长度可变的数组
    • 优点:遍历元素和随机访问元素,效率比较高
    • 缺点:添加和删除需大量移动元素,效率低,按内容查找效率高
      在这里插入图片描述
  • LinkList
    • 采用双向链表存储方式
    • 缺点:遍历和随机访问元素效率低
    • 优点:插入、删除元素效率较高(前提是必须先查询,但是查询效率低,如果插入删除发生在头尾可以减少查询次数)
      在这里插入图片描述

3.2. ArrayList

3.2.1. 使用ArrayList存储多个学生的分数

import java.util.ArrayList;
import java.util.Iterator;

public class TestArrayList1 {
    public static void main(String[] args) {
        ArrayList list = new ArrayList();
        list.add(12);
        list.add(34);
        // 加到指定位置,底层发生了元素大量后移
        list.add(2, 100);
        ArrayList list2 = new ArrayList();
        list2.addAll(0, list);
        // 使用增强for循环输出
        for (Object elem : list) {
            Integer i = (Integer)elem;
            System.out.print(i + "\t"); // 12	34	100
        }
        System.out.println();
        // 使用Interator迭代器输出
        Iterator i = list.iterator();
        // 还有元素,没有就结束循环
        while (i.hasNext()) {
            // 有,就取出
            int elem = (Integer)i.next();
            System.out.print(elem + "\t"); // 12	34	100	
        }
    }
}

3.2.2. 使用泛型保证集合操作的安全和便捷

import java.util.ArrayList;
import java.util.Iterator;

public class TestArrayList2 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<Integer>();
        list.add(1);
        list.add(1, 100);
        ArrayList<Integer> list2 = new ArrayList<Integer>();
        list2.add(3);
        list2.addAll(0, list);
        Iterator<Integer> it = list2.iterator();
        while (it.hasNext()) {
            int elem = it.next();
            System.out.print(elem + "\t"); // 1 100 3
        }
    }
}

3.2.3. ArrayList类的更多方法

import java.util.ArrayList;

public class TestArrayList3 {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.remove(new Integer(2));
        list.set(0, 65);
        // list.clear()
        System.out.println(list.contains(65)); // true
        System.out.println(list.toString()); // [65]
        list.ensureCapacity(100);
    }
}
  • 方法
    • add(E e):向列表的尾部添加指定的元素,返回boolean(可选操作)
    • add(int index, E element):向列表的指定位置添加指定的元素,返回boolean(可选操作)
    • addAll(Collection<? extends E> c): 添加指定collection中的所有元素到此列表的结尾,顺序是指定collection的迭代器返回这些元素的顺序,返回boolean(可选操作)
    • clear():从列表中移除所有元素(可选操作)
    • contains(Object o):如果列表包含指定元素,返回true
    • containsAll(Collection<?> c):如果列表包含指定collection的所有元素,返回true
    • get(int index):返回列表中指定位置的元素
    • isEmpty():如果列表布包含元素,返回true
    • iterator():返回按适当顺序在列表的元素上进行迭代的迭代器
    • remove(int index):移除列表中指定位置的元素(可选操作)
    • removeAll(Collection<?> c):从列表中移除指定collection中包含的其所有元素(可选操作)
    • retainAll(Collection<?> c):仅在列表中保留指定collection中包含的元素(可选操作)
    • set(int index, E element):用指定元素替换列表中指定位置的元素(可选操作)
    • size():返回列表中的元素数量

4. ArrayList和LinkedList

4.1. 理解ArrayList源码

  • ArrayList底层就是一个长度可以动态增长的Object数组
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, Serializable {
    private static final int DEFAULT_CAPACITY = 10;
    private static final Object[] EMPTY_ELEMENTDATA = {};
    private static final Object[] DEFAULTCAPACITY_EMPTY_ELEMENTDATA = {};
    transient Object[] elementData;
    private int size;
}
  • 接口是可以一个方法也不提供的,比如RandomAccess, cloneable, java.io.Serializable
public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess, Cloneable, java.io.Serializable {}
  • JDK1.7中,使用无参数构造方法创建ArrayList对象时,默认底层数组长度时10。JDK1.8中,使用无参数构造方法创建ArrayList对象时,默认底层数组长度是0;第一次添加元素,容量不足就要进行扩容
	public ArrayList() {
        this.elementData = DEFAULTCAPACITY_EMPTY_ELEMENTDATA;
    }
    private static int calculateCapacity(Object[] elementData, int minCapacity) {
        if(elementData == DEFAULTCAPACITY_EMPTY_ELEMENTDATA) {
            return Math.max(DEFAULT_CAPACITY, minCapacity);
        }
        return minCapacity;
    }
  • 容量不足时进行扩容,默认扩容50%,如果扩容50%还不足容纳新增元素,就扩容为能容纳新增元素的最小数量
	private void grow(int minCapacity) {
        int oldCapacity = elementData.length;
        int newCapactiy = oldCapacity + (oldCapacity >> 1);
        if(newCapactiy - minCapacity < 0) newCapactiy = minCapacity;
        if(newCapactiy - MAX_ARRAY_SIZE > 0) newCapactiy = hugeCapacity(minCapacity);
        elementData = Arrays.copyOf(elementData, newCapactiy);
    }
  • ArrayList中提供了一个内部类ltr,实现Iterator接口,实现对集合元素的遍历
	public Iterator<E> iterator() {
        return new ltr();
    }
    private class ltr implements Iterator<E> {
        
    }

4.2. LinkedList的使用

4.2.1. 使用LinkedList存储和出来分数

功能:存储多个学生的分数

  • 具体的执行过程
    • ArrayList:大量的后移元素
    • LinkedList:不需要大量的移动元素,修改节点的指向即可
  • 使用ArrayList还是LinkedList:根据使用场合而定
    • ArrayList:大量的根据索引查询的操作,大量的遍历操作(按照索引0-n-1逐个查询)
    • LinkedList:较多的添加、删除操作
  • 建议:List<Integer> list = new ArrayList<Integer>()
  • 不建议:ArrayList<Integer> list = new ArrayList<Integer>()
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

public class TestLinkedList {
    public static void main(String[] args) {
        // 1. 创建一个ArrayList集合对象
        // ArrayList<Integer> list = new ArrayList<Integer>();
        // LinkedList<Integer> list = new LinkedList<Integer>();
        // List<Integer> list = new ArrayList<Integer>();
        List<Integer> list = new LinkedList<Integer>();
        list.add(1);
        list.add(new Integer(2));
        list.add(0, 3);
        System.out.println(list.size()); // 3
        System.out.println(list); // 3 1 2
        list.remove(1);
        System.out.println(list); // 3 2
        System.out.println(list.isEmpty()); // false
    }
}

4.3. 理解LinkedList的底层源码

  • 底层结构是一个双向链表
public class LinkedList<E> extends AbstractSequentialList<E> implements List<E>, Deque<E>, Cloneable, java.io.Serializable {
    // 节点的数量
    transient int size = 0;
    // 指向第一个节点
    transient Node<E> first;
    // 指向最后一个节点
    transient Node<E> last;
    public LinkedList() {
    }
}
  • 有一个静态内部类Node,表示双向链表的节点
	private static class Node<E> {
        // 存储节点的数据
        E item;
        // 指向后一个节点
        Node<E> next;
        // 指向前一个节点
        Node<E> prev;
        Node(Node<E> prev, E element, Node<E> next) {
            this.item = element;
            this.next = next;
            this.prev = prev;
        }
    }
  • LinkedList实现了Deque接口,所以除了可以作为线性表来使用外,还可以当作队列还栈来使用
    在这里插入图片描述

4.4. Java中栈和队列的实现类

  • public class Stack<E> extends Vector <E> Vetor过时了,被ArrayList替代了,Stack也就过时了
  • public interface Queue<E> extends Collection <E>
  • public interface Deque<E> extends Queue <E>
  • Deque和Queue实现类
    • ArrayDeque:顺序栈,数组
    • LinkedList:链栈、链表

4.4.1. 理解Java中栈和队列的接口和实现类

/*
* push:入栈
* pop:出栈
* peek:获取栈顶元素
* */
public class TestLinkedList2 {
    public static void main(String[] args) {
        Deque<String> deque = new LinkedList<String>();
        deque.push("wyb");
        deque.push("xz");
        System.out.println(deque.size()); // 2
        System.out.println(deque.peek()); // xz
        while (!deque.isEmpty()) {
            String elem = deque.pop();
            System.out.println(elem); // xz wyb
        }
        System.out.println(deque.size()); // 0
    }
}

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

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

相关文章

Python:下载数据集

打开网站&#xff1a;搜索 ​​​​​​https://www.kaggle.com 直接下载即可&#xff08;要登陆注册哦&#xff09;,下载完成一定要放到桌面哦&#xff0c;因为读取的是当前目录 在网页上打开上一篇文章所讲的HelloWorld&#xff0c;如果没有安装请跳转 http://t.csdnimg.cn…

视频教程 - 自研Vue3 Tree组件高级功能:虚拟滚动新增节点实现自动滚动

感谢小伙伴们对本套自研vue3 tree组件教程的关注&#xff0c;在前一篇媲美Element Plus JuanTree终极实战&#xff1a;虚拟滚动的功能演示中发现了小bug&#xff0c;特地整理了相关录屏来说明怎么一步步解决bug的&#xff0c;来回馈小伙伴们的支持。 Tree组件高级功能&#xff…

Photoshop Ps2024苹果(mac)版安装下载,(附win/mac下载链接)

一、简介 PS2024即Photoshop 2024&#xff0c;是一款由Adobe公司开发的图像处理软件。其部分功能介绍如下&#xff1a; - 生成式AI绘图&#xff1a;将Photoshop和生成式AI两个强大的成像引擎结合&#xff0c;用户可通过文本提示在Photoshop内部生成内容&#xff0c;并使用Phot…

基于cubeMX的STM32开启SPI及DMA

1、打开cubeMX后&#xff0c;设置SPI&#xff0c;如下图 2、设置SPI的DMA中断 3、DMA设置 4、SPI的GPIO设置 5、最后生成代码&#xff0c;可以看到工程文件中有dma.c和spi.c 6、使用举例&#xff1a;如幻彩灯的亮灭使用SPIDMA产生的信号波形来控制&#xff0c;在ws2812.c中调用…

Harbor镜像仓库(v2.10.3)附相关自定义配置

目录 一. 环境准备 二. 部署安装 三. 修改网段的方法 四. 配置开机与伴随docker启动 五. 基础使用 1. 创建一个用户 2. docker登录用户 3. 创建项目 4. 推送镜像 六. 自制证书配置HTTPS 一. 环境准备 Harbor 是一个开源的企业级 Docker 镜像仓库&#xff0c;提供了许…

1.4亿中文知识图谱导入Nebula Graph快速体验

1. 史上最大规模的中文知识图谱 Yener 开源了史上最大规模的中文知识图谱—— OwnThink&#xff08;链接&#xff1a;​​https://github.com/ownthink/KnowledgeGraphData​​&#xff0c;数据量为 1.4 亿条。数据以 ​​(实体, 属性, 值)​​ 和 ​​(实体, 关系, 实体)​​…

AI大模型技术的四大核心架构分析

AI大模型技术的四大核心架构演进之路 随着人工智能技术的飞速发展&#xff0c;大模型技术已经成为AI领域的重要分支。 深度剖析四大大模型技术架构&#xff1a;纯粹的Prompt提示词法、Agent Function Calling机制&#xff0c;RAG&#xff08;检索增强生成&#xff09;及Fine-…

基于若依框架开发的Spring Boot+Vue的MES(生产制造执行系统)是一种专为中小型工厂设计的ERP(企业资源计划)系统

基于若依框架开发的Spring BootVue的MES&#xff08;生产制造执行系统&#xff09;是一种专为中小型工厂设计的ERP&#xff08;企业资源计划&#xff09;系统。这个系统旨在帮助这些工厂实现更有效的生产管理、数据收集与分析、设备监控以及质量管理等&#xff0c;从而提高生产…

VMWare虚拟机如何连接U盘

检查配置 1&#xff09;Win R键&#xff0c;输入services.msc&#xff0c;打开服务。 2&#xff09;将AMware USB Arbitration Services 服务开启&#xff0c;并设置为自动启动&#xff1b; 连接U盘 目前作者了解有两种连接方式&#xff0c;如有其他连接方式&#xff0c;欢…

2024关于日本AI 领域TOP12 的大学介绍

1.东京大学 &#xff08;The University of Tokyo&#xff09; 位于&#xff1a;日本东京都文京区本郷七丁目3 番1 号 网址&#xff1a;東京大学 东京大学也被称为UTokyo 或东大&#xff0c;是日本第一所国立大学。作为领先的研究型 大学&#xff0c;东京大学提供基本所有…

JavaFX布局-SplitPane

JavaFX布局-SplitPane 常用属性orientationpaddingdividerPositionsdisable 实现方式Java实现fxml实现 一个拆分至少两个区域的容器支持水平、垂直布局可以拖动区域的大小初始化大小通过比例设置[0,1] 常用属性 orientation 排列方式&#xff0c;Orientation.VERTICAL、Orien…

k8s学习2

k8s 分成Master 负责整个k8s集群管理 node节点&#xff08;工作&#xff09;运行nginx 节点—服务器 kubernetes 组件 kubernetes集群主要由控制节点(Master)、工作节点(Node)组成 Master组件 集群的控制平面&#xff0c;集群的决策 负责管理k8s 集群管理 apiserver Kuber…

Cesium 相机控制器(1)-wheel 实现原理简析

Cesium 相机控制器(1)-wheel 实现原理简析 已经做大量简化, 不是代码最终的样子. Viewer┖ CesiumWidget┖ ScreenSpaceCameraController(_screenSpaceCameraController)┣ CameraEventAggregator(_aggregator) // 相机事件代理┃ ┖ ScreenSpaceEventHandler(_eventHandler…

3.创建了Vue项目,需要导入什么插件以及怎么导入

如果你不知道怎么创建Vue项目,建议可以看一看这篇文章 怎么安装Vue的环境和搭建Vue的项目-CSDN博客 1.在idea中打开目标文件 2.系在一个插件Vue.js 3.下载ELement UI 在Terminal中输入 # 切换到项目根目录 cd vueadmin-vue # 或者直接在idea中执行下面命令 # 安装element-u…

WordPress 轻量级产品官网类主题 CeoNova-Pro_v4.4绕授权开心版

CeoNova-Pro 主题是一款轻量级、且简洁大气、产品官网类主题&#xff0c;定位于高端产品官网、同时包含了知识付费、定制服务、问答社区、论坛交流、网址导航、以及付费产品购买下载等全方位覆盖。 源码下载&#xff1a;ceonova-pro4.4.zip 变更日志 新增虚拟资源隐藏信息增…

limit 以及分页 SQL 语句

目录 1. 作用 2. 演示 3. 分页 SQL 语句 1. 作用 获取结果集的一部分&#xff1b; 2. 演示 &#xff08;1&#xff09;如下&#xff0c;获取表的前三行&#xff1b; &#xff08;2&#xff09;只有一个数字&#xff0c;默认从 0 开始&#xff1b; &#xff08;3&#x…

Linux 项目自动化构建工具 —— make/makefile

Linux 项目自动化构建工具 —— make/makefile 入门使用原理自动化构建递归式自动推导 清理注意 特殊符号 会不会写 makefile&#xff0c;从一个侧面说明了一个人是否具备完成大型工程的能力 一个工程中的源文件不计数&#xff0c;其按类型、功能、模块分别放在若干个目录中&a…

神奇海洋养鱼小程序游戏广告联盟流量主休闲小游戏源码

在海洋养鱼小程序中&#xff0c;饲料、任务系统、系统操作日志、签到、看广告、完成喂养、每日签到、系统公告、积分商城、界面设计、拼手气大转盘抽奖以及我的好友等功能共同构建了一个丰富而互动的游戏体验。以下是对这些功能的进一步扩展介绍&#xff1a; 饲料 任务奖励&a…

使用JWT的SpringSecurity实现前后端分离

1. SpringSecurity完成前后端完全分离 分析&#xff1a; 前后端分离&#xff1a;响应的数据必须为JSON数据&#xff0c;之前响应的是网页 需要修改的代码有&#xff1a; 登录成功需要返回json数据登录失败需要返回json数据权限不足时返回json数据未登录访问资源返回json数据 1.…

英国AI大学排名

计算机学科英国Top10 “计算机科学与信息系统”学科除了最受关注的“计算机科学”专业&#xff0c;还包括了“人工智能”“软件工程”“计算机金融”等众多分支专业。 1.帝国理工学院 Imperial College London 单以计算机专业本科来讲&#xff0c;仅Computing这个专业&#x…