一篇文章让你搞懂Java顺序表

news2024/11/14 16:35:03

目录

一、 线性表的基本介绍

二、顺序表

1、顺序表的概念

2. 创建顺序表类(ArrayList)

2. 增加元素

3. 删除元素

4. 修改某个元素

5. 查找元素

Main类


在数据结构体系中我们将整个数据结构分为两类,一类是线性结构;

线性表是一种在实际中广泛使 用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串...

另一类是非线性结构:

非线性结构,数学用语,其逻辑特征是一个结点元素可能有多个直接前驱和多个直接后继。常见的非线性结构:树、图......

直接前驱就是该数据的前一个数据,直接后继就是该数据的后一个数据。

一、 线性表的基本介绍

【百度百科】:

 线性表是最基本、最简单、也是最常用的一种数据结构。线性表(linear list)是数据结构的一种,一个线性表是n个具有相同特性的数据元素的有限序列。

         线性表中数据元素之间的关系是一对一的关系,即除了第一个和最后一个数据元素之外,其它数据元素都是首尾相接的(注意,这句话只适用大部分线性表,而不是全部。比如,循环链表逻辑层次上也是一种线性表(存储层次上属于链式存储,但是把最后一个数据元素的尾指针指向了首位结点)。

就好像小朋友在排队:

二、顺序表

1、顺序表的概念

 【百度百科】顺序表是在计算机内存中以数组的形式保存的线性表,线性表的顺序存储是指用一组地址连续的存储单元依次存储线性表中的各个元素、使得线性表中在逻辑结构上相邻的数据元素存储在相邻的物理存储单元中,即通过数据元素物理存储的相邻关系来反映数据元素之间逻辑上的相邻关系,采用顺序存储结构的线性表通常称为顺序表。顺序表是将表中的结点依次存放在计算机内存中一组地址连续的存储单元中。

2. 创建顺序表类(ArrayList)

我们这个顺序表用到的是数组,所以我们就可以在这个顺序表中定义一个数组的成员变量,由于顺序表中的元素没有指定是什么类型,那么我们就创建一个泛型类的顺序表,以及一个泛型数组!并且我们还需要一个值来记录数组内元素的个数,那么为了方便,我们还可以利用构造方法初始化我们的数组大小。

代码如下:

public class MyArraylist<E> {
    public E[] elem;
    public int usedSize;//0
    //默认容量
    private static final int DEFAULT_SIZE = 10;
    public MyArraylist() {
        this.elem =(E[]) new Object[DEFAULT_SIZE];
    }
}

我们这里是设置为默认的容量,也可以根据自己想要的大小去重载构造器即可;例如:

  public MyArraylist(int usedSize) {
        this.usedSize = usedSize;
    }

我们的数据结构的各项功能用四个字来概括,无非就是增删改查,以及实现一些特别的方法。

按照我们所说的,我们先来实现增加元素;

2. 增加元素

对于增加元素我们可以选择默认就是在表尾部进行增加,或者在我们指定的位置进行增加,而我们所实现的代码的大致思路如下:

1. 先判断所给的索引是否合理。

2. 先判断是否顺序表满了? 如果满了我们是否要对其扩容,我们实现的代码是要对其进行扩容的。

3. 将整个数组从指定位置一个一个向后移动以一个位置。

add方法:

public void add(int pos, E data) {
        checkIndex(pos);
        if (isFull()) {
            resize();
        }
        for (int i = this.usedSize - 1; i >= pos; i--) {
            elem[i + 1] = elem[i];
        }
        elem[pos] = data;
        usedSize++;
    }

checkIndex方法:

 private void checkIndex(int pos) {//可以是private,也可以是public,这里主要体现了封装性
        if(pos < 0 || pos > usedSize) {
            throw new IndexOutOfException
                    ("pos位置不合法,请检查pos位置的合法性!");
        }
    }

isFull方法:

 public boolean isFull() {//访问权限与checkIndex方法同理
        return this.usedSize == this.elem.length;
    }

resize扩容方法:

为什么我们要按照1.5倍进行扩容,我们可以参考Java提供的ArrayList类:

1.找到提供的add方法,我们发现它有一个

ensureCapacityInternal方法,ctrl+B追溯源码

 2. 里面又调用了

ensureExplicitCapacity方法,继续追

3. 直到我们找到grow方法,继续追

 4.  ​​​直到找到如下这句话:

原来的容量加上原来的容量向右移一位。

private void resize() {
        this.elem = Arrays.copyOf(this.elem,
                (int) 1.5 * this.elem.length);
    }

其他的方法我们也都是参考了ArrayList的底层逻辑,比如:isEmpty,比如contains

 

 我们所有的方法都可以去参考,借鉴底层的逻辑思维,去帮助我们跟好的理解数据结构,我们这一门课程在进行写代码时,借鉴了大量的底层逻辑思想。

默认添加add的重载:

public void add(E data) {
        if (isFull()) {
            resize();
        }
        elem[this.usedSize] = data;
        this.usedSize++;
    }

3. 删除元素

思路如下:

1. 先找到想要删除的数,调用了indexOf方法,如果找不到,则返回-1 ;找到则放回它的下表

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

2. 怎么将元素删除,我们直接将后一个元素覆盖在该元素上即可。

 public void remove(E key) {
        int index = indexOf(key);
        if (index == -1 ) {
            throw new IndexOutOfException("key 不存在该顺序表中," +
                    "请检查您想要删除的key");
        }
        for (int i = index;i < usedSize-1;i++) {
            elem[i] = elem[i+1];
        }
        usedSize --;
        elem[usedSize] = null;
    }

3. 我们提供了

IndexOutOfException类,用于抛出异常

这段逻辑可以任意改

public class IndexOutOfException extends RuntimeException{
    public IndexOutOfException() {
        super();
    }
    public IndexOutOfException(String s) {
        super(s);
    }
}

4. 修改某个元素

思路如下:

我们只需要确保改下表是否合理:

 private void checkGetIndex(int pos) {
        if(pos < 0 || pos >= usedSize) {
            throw new IndexOutOfException
                    ("get获取元素的时候,位置不合法,请检查位置的合法性!");
        }
    }

set方法:

 public void set(int pos, E value) {
        checkGetIndex(pos);
        this.elem[pos] = value;
    }

5. 查找元素

我们提供了查找某个元素和查找整个顺序表

get方法:

  // 获取 pos 位置的元素
    public E get(int pos) {
        return this.elem[pos];
    }

display方法:

1. 我们只需要判断表是否为空表即可

2. 遍历整个数据并打印

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

此外我们还提供了两个方法,一个用于获取整个表的表长size()方法,一个用于清空表的数据clear()方法。

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

    // 清空顺序表
    public void clear() {
//        for (int i = 0; i < usedSize; i++) {
//            elem[i] = Integer.parseInt(null);
//        }
//        usedSize = 0;
//        也可以这样
        usedSize = 0;
    }

这样整个MyArrayList类就结束了(当然,还可以继续添加任意合理的方法),我们来测试一下:

Main类

代码如下:

public class Main {
    public static void main(String[] args) {
        //我们的object可以是任意类型,这里只拿Integer来进行测试
        MyArraylist<Integer> myList = new MyArraylist<>();
        myList.add(1);
        myList.add(2);
        myList.add(3);
        myList.display();
        myList.add(3,2);
        myList.display();
        myList.remove(2);
        myList.display();
        System.out.println(myList.contains(6));
        myList.set(0,7);
        myList.display();
        myList.clear();
        myList.display();
    }
}

 完整代码如下:

MyArratList类

import java.util.Arrays;

@SuppressWarnings("all") // 用于抑制所有警告,注意这里没有分号
public class MyArraylist<E> {
    public E[] elem;
    public int usedSize;//0
    //默认容量
    private static final int DEFAULT_SIZE = 10;
    public MyArraylist() {
        this.elem =(E[]) new Object[DEFAULT_SIZE];
    }

    public MyArraylist(int usedSize) {
        this.usedSize = usedSize;
    }

    /**
     * 打印顺序表:
     * 根据usedSize判断即可
     */
    public void display() {
        if (isEmpty()) {
            return;
        }
        for (int i = 0; i < usedSize; i++) {
            System.out.print(elem[i] + " ");
        }
        System.out.println();
    }
    // 新增元素,默认在数组最后新增
    public void add(E data) {
        if (isFull()) {
            resize();
        }
        elem[this.usedSize] = data;
        this.usedSize++;
    }
    /**
     * 判断当前的顺序表是不是满的!
     *
     * @return true:满   false代表空
     */
    public boolean isFull() {
        return this.usedSize == this.elem.length;
    }
    private boolean checkPosInAdd(int pos) {
        if (pos < 0 || pos > this.usedSize) {
            return false;//不合法
        }
        return true;//合法
    }
    private void checkIndex(int pos) {
        if(pos < 0 || pos > usedSize) {
            throw new IndexOutOfException
                    ("pos位置不合法,请检查pos位置的合法性!");
        }
    }

    // 在 pos 位置新增元素
    public void add(int pos, E data) {
        checkIndex(pos);
        if (isFull()) {
            resize();
        }
        for (int i = this.usedSize - 1; i >= pos; i--) {
            elem[i + 1] = elem[i];
        }
        elem[pos] = data;
        usedSize++;
    }

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

    // 查找某个元素对应的位置
    public int indexOf(E toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

    // 获取 pos 位置的元素
    public E get(int pos) {
        return this.elem[pos];
    }

    private boolean isEmpty() {
        return this.usedSize == 0;
    }

    private void checkGetIndex(int pos) {
        if(pos < 0 || pos >= usedSize) {
            throw new IndexOutOfException
                    ("get获取元素的时候,位置不合法,请检查位置的合法性!");
        }
    }

    // 给 pos 位置的元素设为【更新为】 value
    public void set(int pos, E value) {
        checkGetIndex(pos);
        this.elem[pos] = value;
    }

    /**
     * 删除第一次出现的关键字key
     *
     * @param key
     */
    public void remove(E key) {
        int index = indexOf(key);
        if (index == -1 ) {
            throw new IndexOutOfException("key 不存在该顺序表中," +
                    "请检查您想要删除的key");
        }
        for (int i = index;i < usedSize-1;i++) {
            elem[i] = elem[i+1];
        }
        usedSize --;
        elem[usedSize] = null;
    }

    //扩容
    private void resize() {
        this.elem = Arrays.copyOf(this.elem,
                (int) 1.5 * this.elem.length);
    }

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

    // 清空顺序表
    public void clear() {
//        for (int i = 0; i < usedSize; i++) {
//            elem[i] = Integer.parseInt(null);
//        }
//        usedSize = 0;
//        也可以这样
        usedSize = 0;
    }
}

Main类:

public class Main {
    public static void main(String[] args) {
        //我们的object可以是任意类型,这里只拿Integer来进行测试
        MyArraylist<Integer> myList = new MyArraylist<>();
        myList.add(1);
        myList.add(2);
        myList.add(3);
        myList.display();
        myList.add(3,2);
        myList.display();
        myList.remove(2);
        myList.display();
        System.out.println(myList.contains(6));
        myList.set(0,7);
        myList.display();
        myList.clear();
        myList.display();
    }
}

IndexOutOfException类:
public class IndexOutOfException extends RuntimeException{
    public IndexOutOfException() {
        super();
    }
    public IndexOutOfException(String s) {
        super(s);
    }
}

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

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

相关文章

微电网两阶段鲁棒优化经济调度方法(完美复现)

针对微电网内可再生能源和负荷的不确定性&#xff0c;建立了 min-max-min 结构的两阶段鲁棒优化模型&#xff0c;可得到最恶劣场 景下运行成本最低的调度方案。模型中考虑了储能、需求侧 负荷及可控分布式电源等的运行约束和协调控制&#xff0c;并引入了 不确定性调节参数&…

Java基于springboot+vue+element医疗用品销售购物商城系统 前后端分离

开发背景和意义 网络购物己经成为一个常态化的消费手段&#xff0c;足不出户即可享受互联网发展的红利&#xff0c;对于购物商城的应用&#xff0c;普通消费者目前普遍使用。医疗用品作为一个大众消费的商品&#xff0c;由于其健康的特点&#xff0c;也越来越为大家喜欢&#…

TypeScript 知识点总结

对于有着强制类型语言经验的开发来讲&#xff0c;刚开始接触 JavaScript 的时候&#xff0c;大多都有一种 “心如芒刺&#xff0c;如鲠在喉” 的感觉。 从最初的好感 -——开放包容&#xff0c;到后来的厌恶之情——放荡不羁 TypeScript 犹如黑暗之中的一缕阳光&#xff0c;拯救…

【单片机基础】ADC0832详解

文章目录一、ADC0832介绍1、功能特点2、引脚说明3、ADC0832与单片机接口4、工作时序二、例程一、ADC0832介绍 ADC0832 是美国国家半导体公司生产的一种8 位分辨率、双通道A/D转换芯片。由于它体积小&#xff0c;兼容性&#xff0c;性价比高而深受单片机爱好者及企业欢迎&#x…

Java_笔记_static_静态变量方法工具类_main方法

static表示静态&#xff0c;是Java中的一个修饰符&#xff0c;可以修饰成员方法和成员变量。 一、静态变量: 被static修饰的成员变量 1.特点&#xff1a; 1&#xff09;被该类所有的对象共享。 2&#xff09;不属于对象&#xff0c;属于类。 3&#xff09;随着类的加载而加载…

(个人记录)Ensight后处理EDEM学习笔记

①EDEM计算完毕 ②左上角,点击输出data 先点击一下 然后再把EXPORT FORMAT改为ensight的格式 file name选择要保存到的文件夹,保存格式为.case文件 设置保存的时间步 填入“10”的意思是0.01*10=0.1,在ensight中以0.1的时间步展示结果 点击queries 在ensight里只能…

七段显示译码器

我们会把它放在系统中来显示多位&#xff0c;很多位的表达会用到小数点 12.34 我只想显示&#xff0c;我现实系统的数字大小有一个范围&#xff0c;比如整数四位&#xff0c;小数四位 我显示12.34 就意味着首先两位就是空着&#xff0c;最后两位也是空着 这几位从输入的数字…

Android 基础知识4-1 用户界面简介VIewGroup、Onclick事件处理

引言&#xff1a; 一个好的应用界面的必备条件是&#xff1a;内容清楚、指示明白、屏幕美观和有亲切感。界面通常包含图形和文字。应用界面的设计是对控件进行适当的取舍及功能的选择和处理的过程。在程序设计中&#xff0c;需要对设计的方法反复推敲、琢磨&#xff0c;才能使其…

spfa算法判断负环【什么是负环】【出现负环会怎么样】【牢记,此时不是求最短路】

欢迎观看我的博客&#xff0c;如有问题交流&#xff0c;欢迎评论区留言&#xff0c;一定尽快回复&#xff01;&#xff08;大家可以去看我的专栏&#xff0c;是所有文章的目录&#xff09; 文章字体风格&#xff1a; 红色文字表示&#xff1a;重难点 蓝色文字表示&#xff1a;思…

【推荐题目】

一&#xff0c;题目 1. 猪队友&#xff08;pigmate.cpp&#xff09; 【问题描述】 "不怕神一样的对手&#xff0c;就怕猪一样的队友"&#xff0c;这不&#xff0c;小A需要将小B写的 n 张不同的明信片 放到一一对应的 n 个不同的信封中去&#xff0c;可是不管你信不…

代码不到200行!Tkinter上课点名程序来了

前言 今天给大家分享一个比较有意思的Python应用&#xff0c;使用Tkinter开发了一款上课点名程序&#xff0c;此程序可以用于点名、抽奖代码不到200行&#xff0c;程序简单又实用&#xff0c;分享给到大家&#xff5e; 开发工具 Python版本&#xff1a; 3.8 相关模块&#xff1…

I2C、SPI、CAN、PCIe 对比

唯一标识 在社会上&#xff0c;靠身份证号&#xff0c;来唯一标识一个人。 在计算机的世界里&#xff0c;通过什么来唯一标识一个外设呢&#xff1f;方案还不止一种 I2C 使用地址&#xff08;7 或 10 位&#xff09;来唯一标识一个外设 SPI 使用 CS 引脚来唯一确定通信的外设…

0.安装和配置

我们不要怕&#xff0c;我们要一直向前&#xff0c;为了我们的目标。 对应关系是: https://www.rabbitmq.com/which-erlang.html 安装 Erlang https://www.erlang.org/downloads 选中 64 位 进行下载 下载后&#xff0c;双击 进行安装 选择 安装的路径 路径为&#xff1a; …

[附源码]计算机毕业设计校园招聘系统Springboot程序

项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybatis Maven Vue 等等组成&#xff0c;B/S模式 M…

Android深色主题背景的实现及主题背景颜色互换

layout: post title: Android深色主题背景的实现及主题背景颜色互换 date: 2-12-03 21:52:38 发布 author: ‘zhangtao’ header-img: ‘img/post-bg-2015.jpg’ catalog: false tags: -android -android studio -ide 目录 深色主题背景的优势&#xff1a; 如何实现Android的…

MySQL进阶

文章目录数据库约束NULL约束UNIQUE&#xff1a;唯一约束DEFAULT&#xff1a;默认值约束PRIMARY KEY&#xff1a;主键约束FOREIGN KEY&#xff1a;外键约束表的设计——一对一、一对多、多对多增删改查进阶聚合函数Group by分组having:分组后的条件过滤联合查询内连接外连接自连…

【 第六章 事务操作、事务四大特性、并发事务问题、事务隔离级别】

第六章 事务操作、事务四大特性、并发事务问题、事务隔离级别 1.事务简介&#xff1a; ①事务是一组操作的集合&#xff0c;它是一个不可分割的工作单位&#xff0c;事务会把所有的操作作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这些操作要么同时成功&#xff0…

Kafka - 13 Java 客户端实现消费者消费消息

文章目录1. 独立消费者案例&#xff08;订阅主题&#xff09;2. 独立消费者案例&#xff08;订阅分区&#xff09;3. 消费者组案例1. 独立消费者案例&#xff08;订阅主题&#xff09; 需求&#xff1a;创建一个独立消费者&#xff0c;消费主题中数据&#xff1a; [roothadoo…

Linux系统移植三:移植Kernel生成zImage和dtb文件

Linux系统移植系列 Linux系统移植一&#xff1a;移植U-BOOT 添加自己的板子并编译&#xff08;非petalinux版&#xff09; Linux系统移植二&#xff1a;生成fsbl引导文件并制作BOOT.bin 下载源码包 Xilinx官方linux源码包下载地址&#xff1a;https://github.com/Xilinx/lin…

linux+window+macos下的JDK安装

1. Linux中安装JDK &#xff08;1&#xff09;下载Linux版本的jdk压缩包 &#xff08;2&#xff09;解压 tar -zxvf 压缩包名 例如&#xff1a; tar -zxvf jdk-8u251-linux-x64.tar.gz&#xff08;3&#xff09;在系统配置文件配置java 编辑profile配置文件 vim /etc/prof…