JavaDS —— 顺序表ArrayList

news2024/9/20 20:33:47

顺序表

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

模拟实现

下面是我们要自己模拟实现的方法:

在这里插入图片描述

首先我们要创建一个顺序表,顺序表包含一个数组,一个由于计数的计数器,还有一个默认的初始容量,我这里定义初始容量为5,比较好判断扩容是否成功。这里以整型数组为例:

    private int[] array;
    private int usedSize;//目前数据总数
    private static final int DEFAULT_CAPACITY = 5;//默认容量

默认构造方法

这里我们直接在构造方法里给数组进行初始化:

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

尾插

尾插是指直接在所有数据的后面插入新数据,这里我们要注意数组容量是否已满,所以我们先写一个isFull方法判断数组是否容量已满:

    private boolean isFull() {
        if(usedSize == array.length) {
            return true;
        }
        return false;
    }

这个方法设置成private是因为这个方法只是给本类的方法提供的,不需要对外公开。


如果数组已满,那么我们就需要扩容,这里我扩容2倍:

    private void grow() {
        array = Arrays.copyOf(array,array.length * 2);
    }

现在来写尾插代码:

    public void add(int data) {
        //判满
        if(isFull()) {
            grow();
        }

        //插入数据
        array[usedSize++] = data;
    }

pos位置插入数据

首先我们要先检查pos位置是否合法,如果不合法的话就不用进行插入操作,直接抛出异常,我们先写异常代码:

public class PosException extends RuntimeException{
    public PosException(String message) {
        super(message);
    }
}

检查pos位置是否合法:

    private void checkPosInAdd(int pos) throws PosException {
        if(pos < 0 || pos > usedSize) {
            throw new PosException("pos位置不合法");
        }
    }

现在写插入代码,首先判断pos是否合法,然后判断是否要扩容,最后我们进行插入操作即可,在插入代码中,我们使用try-catch来处理异常。

    public void add(int pos,int data) {
        try{
            checkPosInAdd(pos);//检查位置是否合法
            if(isFull()) {    //判满
                grow();
            }
            //移动数据
            for (int i = usedSize; i >= pos ; i--) {
                array[i+1] = array[i];
            }
            //插入数据
            array[pos] = data;
            usedSize++;
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
    }

contains

是否包含某个元素,使用布尔值进行返回,这里直接遍历数组查找即可。

    public boolean contains(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == toFind){
                return true;
            }
        }
        return false;
    }

indexOf

查找某个元素的下标,找到则返回该元素的下标,没有找到则返回 -1

    public int indexOf(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

get

找到pos位置的元素,这里要注意先判断pos是否合法,但是这里的检查pos和上面我们写过的checkPosInAdd是不一样的,这里的pos必须是有元素的下标范围,也就是不包含usedSize这个下标,因为这个是没有有效数据的,是待插入的空位,所以我们要再写一个检查pos方法:

    private void checkPosInFind(int pos) throws PosException {
        if(pos < 0 || pos >= usedSize) {
            throw new PosException("pos位置不合法");
        }
    }

    public int get(int pos) {
        try{
            checkPosInFind(pos);
            return array[pos];
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
        return -1;
    }

set

更新pos位置的数据,还是要判断pos位置是否合法,这里使用发判断方法应该为checkPosInFind

    public void set(int pos, int data) {
        try{
            checkPosInFind(pos);
            array[pos] = data;
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
    }

remove

删除第一次出现的关键字key

    public void remove(int key) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == key) {
                for (int j = i; j < usedSize - 1; j++) {
                    array[j] = array[j+1];
                }
                usedSize--;
                return;
            }
        }
    }

size

获取顺序表的长度,这里直接返回usedSize即可

    public int size() {
        return usedSize;
    }

display

打印顺序表,该方法是便于测试,真正的顺序表并没有这个方法

    public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

clear

清空顺序表,直接将usedSize赋值为0即可,下次使用的时候,会直接覆盖之前的数据的。

    public void clear() {
        usedSize = 0;
    }

完整代码

import java.util.Arrays;

public class MyArrayList {
    private int[] array;
    private int usedSize;//目前数据总数
    private static final int DEFAULT_CAPACITY = 5;//默认容量

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

    /*
    判满,满则返回true,否则返回false
     */
    private boolean isFull() {
        if(usedSize == array.length) {
            return true;
        }
        return false;
    }

    //扩容 2倍扩容
    private void grow() {
        array = Arrays.copyOf(array,array.length * 2);
    }

    //尾插
    public void add(int data) {
        //判满
        if(isFull()) {
            grow();
        }

        //插入数据
        array[usedSize++] = data;
    }

    //判断pos是否合法
    /*
      不合法则抛出异常
      增加方法
    */
    private void checkPosInAdd(int pos) throws PosException {
        if(pos < 0 || pos > usedSize) {
            throw new PosException("pos位置不合法");
        }
    }

    //指定pos位置插入数据
    public void add(int pos,int data) {
        try{
            checkPosInAdd(pos);//检查位置是否合法
            if(isFull()) {    //判满
                grow();
            }
            //移动数据
            for (int i = usedSize; i >= pos ; i--) {
                array[i+1] = array[i];
            }
            //插入数据
            array[pos] = data;
            usedSize++;
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
    }

    //是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == toFind){
                return true;
            }
        }
        return false;
    }

    //查找某个元素的下标
    public int indexOf(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    //判断pos是否合法
    /*
      查找方法
      不合法则抛出异常
    */
    private void checkPosInFind(int pos) throws PosException {
        if(pos < 0 || pos >= usedSize) {
            throw new PosException("pos位置不合法");
        }
    }

    //获取pos位置的元素
    public int get(int pos) {
        try{
            checkPosInFind(pos);
            return array[pos];
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
        return -1;
    }

    //更新pos位置的数据
    public void set(int pos, int data) {
        try{
            checkPosInFind(pos);
            array[pos] = data;
        }catch (PosException e) {
            System.out.println("pos位置不合法!");
            e.printStackTrace();
        }
    }

    //删除第一次出现的关键字key
    public void remove(int key) {
        for (int i = 0; i < usedSize; i++) {
            if(array[i] == key) {
                for (int j = i; j < usedSize - 1; j++) {
                    array[j] = array[j+1];
                }
                usedSize--;
                return;
            }
        }
    }

    //获取顺序表的长度
    public int size() {
        return usedSize;
    }

    //打印顺序表,该方法是便于测试,真正的顺序表并没有这个方法
    public void display() {
        for (int i = 0; i < usedSize; i++) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }

    //清空顺序表
    public void clear() {
        usedSize = 0;
    }
}

ArrayList 的使用

Java已经封装好顺序表供我们使用,就是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 的下标

更多详细的方法可自行查阅官方文档

上面很多方法是我们自己模拟实现过的,这里就不一一举例演示。

ArrayList 的成员方法

在这里插入图片描述

ArrayList 构造方法

一共提供了三个构造方法:

方法解释
ArrayList()无参构造
ArrayList(Collection<? extends E> c)利用其他 Colletion 构建 ArrayList
ArrayList(int initialCapacity)指定顺序表初始容量

ArrayList(int initialCapacity)指定顺序表初始容量看一下源码还是很好理解的,初始容量大于零就开辟一块连续的空间,等于零就给一个空数组,小于零则抛出异常。

在这里插入图片描述

首先要知道下面的关系图:
在这里插入图片描述

从上图我们可以得知ArrayList是包含Collection这个接口的,所以可以接收Colletion的参数,Colletion后面的<? extends E> 中的 ? 是通配符,后面的文章会提到。

在这里插入图片描述


我们重点是看无参的构造方法:

在这里插入图片描述

直接赋值一个空数组,大家来看一下下面的代码,明明是空数组,但是为什么可以直接add而不会报错呢?

    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(10);
        list.add(20);
        System.out.println(list);
    }

在这里插入图片描述

我们点过去看看源码是什么:

在这里插入图片描述

在这里插入图片描述

到了这里大家应该明白了,在使用add的时候,我们看到源码里写了当 s == 数组长度的时候,Java底层会帮我们自动扩容。

ArrayList 实例化

我们经常使用List或者ArrayList来接收顺序表实例化的对象.

        List<Integer> list = new ArrayList<>();
        ArrayList<Integer> list2 = new ArrayList<>();

由于List是ArrayList的接口,所以可以接收,但是注意List是接口意味着不能进行实例化,使用List接收的参数只能使用List有点方法,由于ArrayList有很多接口,一定是拓展了很多东西的,如果List接口没有包含的方法,使用List接收的参数不能调用其他方法,但是使用ArrayList接收的话,所有ArrayList实现的方法都是可以调用的,只要是公开访问即可.

ArrayList 遍历方法

ArrayList 可以使用三方方式遍历:for循环+下标、foreach、使用迭代器,还可以直接打印里面的内容。

        int size = list.size();
        for (int i = 0; i < size; i++) {
            System.out.print(list.get(i) + " ");
        }
        System.out.println();

无论是Integer还是int接收元素,Java底层会帮我们自动拆箱的.

        for (int x: list) {
            System.out.print(x + " ");
        }
        System.out.println();
        for (Integer y: list) {
            System.out.print(y + " ");
        }
        System.out.println();
        ListIterator<Integer> it =  list.listIterator(list.size());
        while (it.hasPrevious()) {
            System.out.print(it.previous()+" ");
        }
        System.out.println();

Java的ArrayList的父类是重写过toString方法的.

        System.out.println(list);

在这里插入图片描述

实践

杨辉三角

在这里插入图片描述

在这里插入图片描述

这里要注意 List<List< Integer>> ,这个意思表示外面的list的元素是list,里面的list的元素是Integer,例如下图所示:类似二维数组~

在这里插入图片描述

代码:

class Solution {
    public List<List<Integer>> generate(int numRows) {
        List<List<Integer>> list = new ArrayList<>();
        List<Integer> list0 = new ArrayList<>();
        list0.add(1);
        list.add(list0);

        for(int i=1;i<numRows;i++) {
            List<Integer> list1 = new ArrayList<>();
            for(int j=0;j<=i;j++) {
                if(j==0 || j==i) {
                    list1.add(1);
                } else {
                    list1.add(list.get(i-1).get(j-1) + list.get(i-1).get(j));
                }
            }
            list.add(list1);
        }

        return list;
    }
}

洗牌功能实现

public class Card {
    private int number;
    private String cardColor;

    public Card(int number, String cardColor) {
        this.number = number;
        this.cardColor = cardColor;
    }

    @Override
    public String toString() {
        return "Card{" +
                cardColor + '\'' +
                number +
                '}';
    }
}
import java.util.ArrayList;
import java.util.List;
import java.util.Random;

public class PlayCard {
    private static final String[] cardColor = {"♦","♣","♥","♠"};

    //购买52张牌
    public List<Card> buyCards() {
        List<Card> list = new ArrayList<>();
        for (int i = 1; i <= 13; i++) {
            for (int j = 0; j < 4; j++) {
                Card card = new Card(i,cardColor[j]);
                list.add(card);
            }
        }
        return list;
    }

    //洗牌
    public void shuffle(List<Card> list) {
        Random random = new Random();
        int size = list.size();
        for (int i = 0; i < size; i++) {
            int index = random.nextInt(size);//生成 0 ~ i-1 的随机数
            Card card = list.get(index);
            list.set(index,list.get(i));
            list.set(i,card);
        }
    }

    //发牌
    public List<List<Card>> deal(List<Card> cards) {
        List<List<Card>> list = new ArrayList<>();
        //创建三个人
        List<Card> list0 = new ArrayList<>();
        List<Card> list1 = new ArrayList<>();
        List<Card> list2 = new ArrayList<>();

        list.add(list0);
        list.add(list1);
        list.add(list2);

        int size = cards.size();
        int size2 = list.size();

        int count = 0;
        boolean flag = true;
        while(flag) {
            for (int j = 0; j < size2; j++) {
                list.get(j).add(cards.remove(0));
                count++;
                if(count == size){
                    flag = false;
                    break;
                }
            }
        }

        return list;
    }
}

这里要注意随机数的建立,首先先实例化Ramdom对象,然后使用nextInt方法,nextInt(int bound),生成的随机数范围是0~bound-1.

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

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

相关文章

C++初探究

概述 C可以追溯到1979年&#xff0c;C之父Bjarne Stroustrup在在使用C语言研发工作时发现C语言的不足&#xff0c;并想要将其改进&#xff0c;到1983年&#xff0c;Bjarne Stroustrup在C语言的基础上添加了面向对象编程的特性&#xff0c;设计出了C的雏形。 网址推荐 C官方文…

C++继承(一文说懂)

目录 一&#xff1a; &#x1f525;继承的概念及定义1.1 继承的概念1.2 继承定义1.2.1 定义格式1.2.2 继承关系和访问限定符1.2.3 继承基类成员访问方式的变化 二&#xff1a;&#x1f525;基类和派生类对象赋值转换三&#xff1a;&#x1f525;继承中的作用域四&#xff1a;&a…

太多项会毁了回归

「AI秘籍」系列课程&#xff1a; 人工智能应用数学基础 人工智能Python基础 人工智能基础核心知识 人工智能BI核心知识 人工智能CV核心知识 多项式回归的过度拟合及其避免方法 通过添加现有特征的幂&#xff0c;多项式回归可以帮助你充分利用数据集。它允许我们甚至使用简…

Java学习高级二

Java是单继承的 Object类 方法重写 Java子类访问 – 就近原则 子类构造器的特点 多态 Java–final

【豆包AI】北京春田知韵

看到有国内AI上线了&#xff0c;网络信息那么多&#xff0c;我该怎么找它的官网呢&#xff1f; 找官方网站3步 1百度 关于抖音豆包的网站是哪个?【www.doubao.com】 豆包属于哪个公司&#xff1f;【北京春田知韵科技有限公司】 www.doubao.com 2查询备案号 PC版本的安装…

理解算法复杂度:时间复杂度详解

引言 在计算机科学中&#xff0c;算法复杂度是衡量算法效率的重要指标。时间复杂度和空间复杂度是算法复杂度的两个主要方面。在这篇博客中&#xff0c;我们将深入探讨时间复杂度&#xff0c;了解其定义、常见类型以及如何进行分析。 什么是时间复杂度&#xff1f; 时间复杂度…

论文《Generalizable Adversarial Attacks Using Generative Models》笔记

【DAGAER】传统的攻击方法依赖于约束优化范式&#xff0c;具有局限性&#xff0c;例如经典的Nettack攻击方法。本文提出了一个统一的白盒对抗攻击生成框架&#xff0c;该方法学习了目标域的深度生成模型&#xff0c;不是在原始输入空间中生成对抗性例子&#xff0c;而是学习在一…

elk在宝塔中的简单部署和使用

ELK是什么&#xff1f;了解elk “ELK” 是 Elasticsearch、Logstash 和 Kibana 三个开源软件的首字母缩写。这三个软件一起常被称为 “ELK Stack” 或 “Elastic Stack”。它们主要用于日志管理和分析&#xff0c;提供了强大的数据搜索、分析和可视化功能。 Elasticsearch&am…

C++初阶学习第一弹——入门学习C++

目录 1.什么是C 2.C关键字 3.命名空间 3.1命名空间的定义 3.2命名空间的使用 1、加命名空间名称及作用域限定符 2、使用 using 将命名空间中某个成员引入 3.使用using namespace 命名空间名称 引入 4.C输入&输出 5.缺省参数 5.1 缺省参数概念 5.2缺省参数分类 6. …

Dungeonborne卡顿延迟怎么办?这样降低Dungeonborne延迟

Dungeonborne将第一人称的动作的即时性和经典的西幻RPG职业设计深度结合&#xff0c;带来无与伦比的游戏体验。玩家在游戏中扮演一位从神秘地牢中醒来的勇士&#xff0c;他必须面对各种未知的敌人和挑战&#xff0c;逐渐揭开自己的身世之谜。在这个充满魔法和奇迹的世界里&…

【计算机毕业设计】015基于weixin小程序校园防疫

&#x1f64a;作者简介&#xff1a;拥有多年开发工作经验&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的项目或者毕业设计。 代码可以私聊博主获取。&#x1f339;赠送计算机毕业设计600个选题excel文件&#xff0c;帮助大学选题。赠送开题报告模板&#xff…

基于MATLAB的PEF湍流风场生成器模拟与仿真

目录 1.课题概述 2.系统仿真结果 3.核心程序与模型 4.系统原理简介 5.完整工程文件 1.课题概述 基于MATLAB的PEF湍流风场生成器模拟与仿真。PEF&#xff08;Primitive Equations Formulation&#xff09;湍流风场模型&#xff0c;是大气科学和气象学中用来描述大气流动和气…

WebOffice在线编微软Offfice,并以二进制流的形式打开Word文档

在日常办公场景中&#xff0c;我们经常会遇到这种场景&#xff1a;我们的合同管理系统的各种Word,excel,ppt数据都是以二进制数组的形式存储在数据库中&#xff0c;如何从数据库中读取二进制数据&#xff0c;以二进制数据作为参数&#xff0c;然后加载到浏览器的Office窗口&…

【已解决】腾讯云安装了redis,但是本地访问不到,连接不上

汇总了我踩过的所有问题。 查看配置文件redis.conf 1、把bind 127.0.0.1给注释掉&#xff08;前面加个#就是&#xff09;或者改成bind 0.0.0.0&#xff0c;因为刚下载时它是默认只让本地访问。&#xff08;linux查找文档里的内容可以输入/后面加需要匹配的内容&#xff0c;然后…

2024人工智能大会_强化学习论坛相关记录

求解大规模数学优化问题 规划也称为优化 四要素&#xff1a;数据、变量、目标、约束 将一个简单的数学规划问题项gpt进行提问&#xff0c;GPT给了一个近似解&#xff0c;但不是确切的解。 大模型的训练本身就是一个优化问题。 大模型是如何训练的&#xff1f;大模型训练通常使…

Unity通过NDK实现C#与C++之间的相互调用

由于一些历史遗留问题&#xff0c;我们项目还在使用一套C实现的Box2D定点数的库&#xff0c;由于最近修改了视野算法所以需要重新打包安卓的【.so】文件&#xff0c;特此记录 1、关于NDK 在Android平台&#xff0c;C/C需通过NDK编译成动态链接库.so文件&#xff0c;然后C#中通过…

MATLAB基础应用精讲-【数模应用】分层聚类(附python代码实现)

目录 前言 知识储备 层次聚类 1. 算法解读: 2. 步骤和细节: 3. 举例: 4. 算法评价: 5. 算法的变体: 算法原理 基本思想 分层聚类网络的原理 分层聚类网络的优势 分层聚类网络的应用领域 SPSSAU 分层聚类案例 1、背景 2、理论 3、操作 4、SPSSAU输出结果…

STM32智能机器人导航系统教程

目录 引言环境准备智能机器人导航系统基础代码实现&#xff1a;实现智能机器人导航系统 4.1 数据采集模块 4.2 数据处理与导航算法 4.3 通信与网络系统实现 4.4 用户界面与数据可视化应用场景&#xff1a;机器人导航应用与优化问题解决方案与优化收尾与总结 1. 引言 智能机器…

如何找到关于目标检测小论文的创新点

深度学习目标检测的小论文创新点 数据集预处理创新 主要包括图像增强、图像去雾、图像融合和图像降噪 例子: 比如在研究方向是检测晚上或者天气不好时骑电动车的人是否佩戴了安全头盔。一般的检测可能只能检测到正常天气情况下的骑电动车的人&#xff0c;而对于大雾天气和晚上…

LT7911UX 国产原装 一拖三 edp 转LVDS 可旋转 可缩放

2.一般说明 该LT7911UX是一种高性能Type-C/DP1.4a到MIPI或LVDS芯片的VR/显示应用。HDCP RX作为HDCP转发器的上游&#xff0c;可以与其他芯片的HDCP TX配合实现转发器功能。 对于DP1.4a输入&#xff0c;LT7911UX可配置为1/2/4通道。自适应均衡使其适用于长电缆应用&#xff0c;最…