【数据结构】 List与顺序表及接口的实现

news/2024/5/20 5:47:47 标签: 数据结构, list, 顺序表, java

文章目录

  • 什么是List
  • 常见接口介绍
  • 线性表
  • 顺序表
    • 顺序表接口的实现
      • add在末尾新增元素
      • 在 pos 位置新增元素
      • 判定是否包含某个元素
      • 查找某个元素对应的位置
      • 获取 pos 位置的元素
      • 给 pos 位置的元素设为 value
      • 删除第一次出现的关键字key
      • 获取顺序表的长度
      • 清空顺序表
  • 顺序表的优缺点
    • 优点:
    • 缺点:
  • 总结

什么是List

在集合框架中,List是一个接口,继承自Collection。
在这里插入图片描述
Collection也是一个接口,该接口中规范了后序容器中常用的一些方法,具体如下所示:
在这里插入图片描述
Iterable也是一个接口,表示实现该接口的类是可以逐个元素进行遍历的,具体如下:
在这里插入图片描述
List 的官方文档

站在数据结构的角度来看,List就是一个线性表,即n个具有相同类型元素的有限序列,在该序列上可以执行增删改查以及变量等操作。

常见接口介绍

List中提供了好的方法,具体如下:
在这里插入图片描述
虽然方法比较多,但是常用方法如下:
在这里插入图片描述
注意:List是个接口,并不能直接用来实例化

线性表

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

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

顺序表

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

在数组上完成数据的增删查改

顺序表接口的实现

我们现在有这样一个SepList接口为:

java">public interface SepList  {
    // 新增元素,默认在数组最后新增
    void add(int data);
    // 在 pos 位置新增元素
    void add(int pos, int data);
    // 判定是否包含某个元素
    boolean contains(int toFind);
    // 查找某个元素对应的位置
    int indexOf(int toFind);
    // 获取 pos 位置的元素
    int get(int pos);
    // 给 pos 位置的元素设为 value
    void set(int pos, int value);
    //删除第一次出现的关键字key
    void remove(int key);
    // 获取顺序表长度
    int size();
    // 清空顺序表
    void clear();
}

这里博主将在一个MyArrayList类里面实现这些接口

java">public class MyArrayList implements SepList  {
    private int[] elem;//数组
    private int usedSize;//记录有效的数据的个数
    private static final int DEFAULT_SIZE = 10;//最初的数据容量

    public MyArrayList() {
        this.elem = new int[DEFAULT_SIZE];
    }
    // 新增元素,默认在数组最后新增
    public void add(int data) { }
    // 在 pos 位置新增元素
    public void add(int pos, int data) { }
    // 判定是否包含某个元素
    public boolean contains(int toFind) { return true; }
    // 查找某个元素对应的位置
    public int indexOf(int toFind) { return -1; }
    // 获取 pos 位置的元素
    public int get(int pos) { return -1; }
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value) { }
    //删除第一次出现的关键字key
    public void remove(int key) { }
    // 获取顺序表长度
    public int size() { return 0; }
    // 清空顺序表
    public void clear() { }
}

add在末尾新增元素

在增加一个元素前,我们需要对该顺序表进行判断,判断是否已满,若满则需要进行扩容

每增加一个元素,我们我们记录有效个数的usedSize加1

java">// 新增元素,默认在数组最后新增
    public void add(int data) {
        //判断数组是否已经被装满
        if(usedSize >= this.elem.length) {
            //被装满后需要进行扩容
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        this.elem[this.usedSize] = data;
        usedSize++;
    }

在 pos 位置新增元素

在增加一个元素前,我们需要对该顺序表进行判断,判断是否已满,若满则需要进行扩容

我们还需要多pos进行一个判断,判断它是否合法,如果不合法,我们抛出异常进行提醒
在这里插入图片描述

在pos位置增加元素,需要将pos位置及以后的元素进行后移一位,然后再在pos位置新增元素
在这里插入图片描述

每增加一个元素,我们我们记录有效个数的usedSize加1

java">//自定义异常
class PosWrongfulException extends RuntimeException {
    public PosWrongfulException(String message) {
        super(message);
    }
}
 // 在 pos 位置新增元素
    public void add(int pos, int data) throws PosWrongfulException {
        //判断数组是否已经被转满
        if(usedSize >= this.elem.length) {
            //被装满后需要进行扩容
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        if(pos < 0 || pos > this.usedSize) {
            System.out.println("pos位置不合法!");
            throw new PosWrongfulException("pos位置不合法");
        }
        for(int i = this.usedSize;i >= pos;i--) {
            //pos位置以及pos位置以后的数据整体进行后移
            this.elem[i] = this.elem[i-1];
        }
        this.elem[pos] = data;
        usedSize++;
    }

判定是否包含某个元素

遍历即可

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

查找某个元素对应的位置

对数组进行遍历,有的话返回相应的数组下标就好,没有返回-1

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

获取 pos 位置的元素

获取前我们得进行判断,该顺序表类元素不能为空

我们还得对pos进行是否合法得判断

java">//自定义的异常
class PosWrongfulException extends RuntimeException {
    public PosWrongfulException(String message) {
        super(message);
    }
}
class EmptyException extends RuntimeException {
    public EmptyException(String message) {
        super(message);
    }
}

  // 获取 pos 位置的元素
    public int get(int pos)throws PosWrongfulException {
        if(this.usedSize == 0)
        {
            throw new EmptyException("当前顺序表为空!");
        }
        if(pos < 0 || pos > this.usedSize) {
            System.out.println("pos位置不合法!");
            throw new PosWrongfulException("pos位置不合法");
        }
        return this.elem[pos];
    }

给 pos 位置的元素设为 value

我们依旧需要判断pos的合法性,前面已经自定义了该异常,这里就不再进行定义了

然后将pos位置的元素改为value就好

java">// 给 pos 位置的元素设为 value
    public void set(int pos, int value) {
        if(pos < 0 || pos > this.usedSize) {
            System.out.println("pos位置不合法!");
            throw new PosWrongfulException("pos位置不合法");
        }
        this.elem[pos] = value;
    }

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

我们依旧需要判断数组是否为空

遍历数组,若没有我们要删除的元素,我们便进行提示后退出

若有,则只需要用后面的数据对前面进行覆盖就好

java"> //删除第一次出现的关键字key
    public void remove(int key) {
        if(this.usedSize == 0) {
            throw new EmptyException("顺序表为空!");
        }
        int index = this.indexOf(key);
        if(index == -1) {
            System.out.println("没有这个数字");
            return;
        }
        //进行覆盖
        for (int i = index; i < size()-1; i++) {
            this.elem[i] = this.elem[i+1];
        }
        //如果不是基本类型,将usedSize下标置为空
        //this.elem[this.usedSize] = null;
        this.usedSize--;

    }

获取顺序表的长度

这个就非常简单了,只需要返回usedSize就好

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

清空顺序表

对于当前基本类型的数据来说,只需要将usedSize置为0就好

java"> public void clear() {
        this.usedSize=0;
    }

顺序表的优缺点

线性表的顺序存储结构,在存、读数据时,不管是哪个位置,时间复杂度都是O(1);而插入或删除时,时间复杂度都是O(n)。这就说明,它比较适合元素个数不太变化,而更多是存取数据的应用。当然,它的优缺点还不只这些……

优点:

无需为表示表中元素之间的逻辑关系而增加额外的存储空间可以快速地存取表中任一位置的元素

缺点:

插入删除操作需要移动大量元素,当线性表长度变化较大时,难以确定存储空间的容量,造成存储空间的碎片

总结

关于《【数据结构】 List与顺序表及接口的实现》就讲解到这儿,感谢大家的支持,欢迎各位留言交流以及批评指正,如果文章对您有帮助或者觉得作者写的还不错可以点一下关注,点赞,收藏支持一下!


http://www.niftyadmin.cn/n/4945605.html

相关文章

java初级算法(杨辉三角)

java初级算法&#xff08;杨辉三角&#xff09; java初级算法&#xff08;杨辉三角&#xff09;内容&#xff1a;思路解法&#xff1a;代码实现 学习时间&#xff1a;2023/08/16 java初级算法&#xff08;杨辉三角&#xff09; 每日一算法&#xff1a;杨辉三角 内容&#xff1a…

SpringBoot案例 调用第三方接口传输数据

一、前言 最近再写调用三方接口传输数据的项目&#xff0c;这篇博客记录项目完成的过程&#xff0c;方便后续再碰到类似的项目可以快速上手 项目结构&#xff1a; 二、编码 这里主要介绍HttpClient发送POST请求工具类和定时器的使用&#xff0c;mvc三层架构编码不做探究 pom.x…

如何使用Java代码收集网站所有功能

使用Java代码收集网站所有功能的步骤可以这么实现: 1. 使用JSoup等工具解析网站首页HTML,获取超链接、表单等元素。 Document doc JSoup.connect("http://website.com").get(); Elements links doc.select("a[href]"); Elements forms doc.select(&qu…

嵌入式系统中如何选择RTC电池?

RTC&#xff08;Real Time Clock&#xff09;是一种用于提供系统时间的独立定时器&#xff0c;它可以在系统断电或低功耗模式下继续运行&#xff0c;只需要一个后备电池作为供电源。在嵌入式系统中&#xff0c;选择合适的RTC电池时非常关键的&#xff0c;它会影响系统时间的准确…

UDP数据报结构分析(面试重点)

在传输层中有UDP和TCP两个重要的协议&#xff0c;下面将针对UDP数据报的结构进行分析 UDP结构图示 UDP报头结构的分析 UDP报头有4个属性&#xff0c;分别是源端口&#xff0c;目的端口&#xff0c;UDP报文长度&#xff0c;校验和&#xff0c;它们都占16位2个字节&#xff0c;所…

【Spring】注解开发——第三方Bean管理

1、简介 当需要管理第三方的Bean时&#xff0c;由于不是我们自己定义的类&#xff0c;所以不能使用Component 注解&#xff0c;也无法在配置类中进行扫包。 2、实现 实现第三方Bean的注入只需要两步即可。 第一步定义一个方法返回该类型的对象 第二步使用Bean注解&#xff0c…

MySQL 自增 ID 默认从 1 开始,如何设置自增 ID 从 0 开始

MySQL 是一种关系型数据库&#xff0c;它是世界上最流行的关系型数据库之一。在 MySQL 中&#xff0c;自增是一种非常有用的功能&#xff0c;它可以自动给主键赋值&#xff0c;并保证每个主键是唯一的。然而&#xff0c;许多人不知道的是&#xff0c;MySQL 默认情况下从 1 开始…

CSS自己实现一个步骤条

前言 步骤条是一种用于引导用户按照特定流程完成任务的导航条&#xff0c;在各种分步表单交互场景中广泛应用。例如&#xff1a;在HIS系统-门诊医生站中的接诊场景中&#xff0c;我们就可以使用步骤条来实现。她的执行步骤分别是&#xff1a;门诊病历>遗嘱录入>完成接诊…