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

news2024/11/17 7:42:14

文章目录

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

什么是List

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

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

常见接口介绍

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

线性表

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

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

顺序表

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

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

顺序表接口的实现

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

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类里面实现这些接口

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

// 新增元素,默认在数组最后新增
    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

//自定义异常
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++;
    }

判定是否包含某个元素

遍历即可

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

查找某个元素对应的位置

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

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

获取 pos 位置的元素

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

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

//自定义的异常
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就好

// 给 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

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

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

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

 //删除第一次出现的关键字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就好

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

清空顺序表

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

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

顺序表的优缺点

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

优点:

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

缺点:

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

总结

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

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

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

相关文章

网络通信原理UDP协议(第五十课)

UDP协议:用户数据包协议,无连接、不可靠,效率高 字段长度描述Source Port2字节标识哪个应用程序发送(发送进程)。Destination Port2字节标识哪个应用程序接收(接收进程)。Length2字节UDP首部加上UDP数据的字节数,最小为8。Checksum2字节覆盖UDP首部和UDP数据,是可…

网络通信原理TCP的四次断开连接(第四十九课)

FIN:发端完成发送任务标识。用来释放一个连接。FIN=1表明此报文段的发送端的数据已经发送完毕,并要求释放连接。 SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的序号。 序列号为X ACK :确认号 。 …

【操作系统】24王道考研笔记——第二章 进程与线程

第二章 进程与线程 一、进程与线程 1.进程的概念 程序&#xff1a;是静态的&#xff0c;就是个存放在磁盘里的可执行文件&#xff0c;如&#xff1a;QQ.exe。 进程&#xff1a;是动态的&#xff0c;是程序的一次执行过程&#xff0c;如&#xff1a;可同时启动多次QQ程序 引…

stable diffusion基础

整合包下载&#xff1a;秋叶大佬 【AI绘画8月最新】Stable Diffusion整合包v4.2发布&#xff01; 参照&#xff1a;基础04】目前全网最贴心的Lora基础知识教程&#xff01; VAE 作用&#xff1a;滤镜微调 VAE下载地址&#xff1a;C站&#xff08;https://civitai.com/models…

目录扫描工具—dirsearch使用指南

一&#xff1a;工具简介 dirsearch是一个基于Python3的命令行工具&#xff0c;旨在对web服务器中的目录和文件进行暴力破解&#xff0c;既暴力扫描页面结构&#xff0c;包括网页中的目录和文件。 下载地址&#xff1a; 1&#xff1a; https://github.com/maurosoria/dirsear…

2023河南萌新联赛第(六)场:河南理工大学-L 阴晴不定的大橘学长

2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学-L 阴晴不定的大橘学长 https://ac.nowcoder.com/acm/contest/63602/L?&headNavacm 文章目录 2023河南萌新联赛第&#xff08;六&#xff09;场&#xff1a;河南理工大学-L 阴晴不定的大橘学长题…

【RP2040】香瓜树莓派RP2040之仿真调试

本文最后修改时间&#xff1a;2022年08月23日 01:57 一、本节简介 本节以树莓派pico开发板为例&#xff0c;介绍如何使用一个pico作为仿真器&#xff0c;给另一个pico仿真调试代码。 二、实验平台 1、硬件平台 1&#xff09;树莓派pico开发板 ①树莓派pico开发板*2 ②micr…

网络通信原理传输层TCP三次建立连接(第四十八课)

ACK :确认号 。 是期望收到对方的下一个报文段的数据的第1个字节的序号,即上次已成功接收到的数据字节序号加1。只有ACK标识为1,此字段有效。确认号X+1SEQ:序号字段。 TCP链接中传输的数据流中每个字节都编上一个序号。序号字段的值指的是本报文段所发送的数据的第一个字节的…

使用 Ansible Galaxy 安装角色

使用 Ansible Galaxy 安装角色 使用 Ansible Galaxy 和要求文件 /home/curtis/ansible/roles/requirements.yml 。从以下 URL 下载角色并安装到 /home/curtis/ansible/roles &#xff1a; http://rhgls.area12.example.com/materials/haproxy.tar 此角色的名称应当为 balancer …

layui下拉框select 弹出层在最外层

出现问题如图所示 想要的效果是如下 这样的效果只需一行代码就能解决 .layui-layer-page .layui-layer-content{overflow: visible!important;}

生信豆芽菜-差异基因富集分析

网址&#xff1a;http://www.sxdyc.com/enrichmentEnrich 该工具使用R 语言的clusterProfiler包对关键基因集进行GO和KEGG富集分析&#xff0c;注意这个的关键基因集可以是差异基因&#xff0c;WGCNA的module基因&#xff0c;也可以是表型相关的基因集 1、数据准备 准备一个基因…

关于统一事件管理,一定有你想知道的(二)

本文部分内容来源于布博士----擎创科技资深产品专家 哈喽~又见面啦~ 上期内容我们说到了事件以及事件管理&#xff0c;戳这里一键恢复上期精彩内容&#xff1a;关于统一事件管理&#xff0c;一定有你想知道的&#xff08;一&#xff09; 这期主要带大家看看事件管理是怎么运用…

spring官方文档浅翻译(1)

文章目录 IOC容器IOC容器和beans的介绍实例化 BeanBeanFactory&#xff1a;ApplicationContext 容器概述配置元数据实例化容器组合基于xml的配置元数据使用容器 bean的概述命名bean别名的使用 实例化bean构造函数实例化静态工厂实例化实例工厂方法bean 在运行时的实际类型 依赖…

学习笔记|基于Delay实现的LED闪烁|模块化编程|SOS求救灯光|STC32G单片机视频开发教程(冲哥)|第八集:实现LED闪烁(下)

文章目录 2 函数的使用1.函数定义&#xff08;需要带类型&#xff09;2.函数声明&#xff08;需要带类型&#xff09;3.函数调用 3 新建文件&#xff0c;使用模块化编程新建xxx.c和xxx.h文件xxx.h格式&#xff1a;调用头文件验证代码调用&#xff1a;完整的文件结构如下&#x…

使用 RHEL 系统角色

使用 RHEL 系统角色 安装 RHEL 系统角色软件包&#xff0c;并创建符合以下条件的 playbook /home/curtis/ansible/selinux.yml &#xff1a; 在所有受管节点上运行 使用 selinux 角色 将角色配置为以强制执行状态使用SELinux yum install rhel-system-roles.noarch su - curti…

七夕送礼指南:这几款礼物不仅颜值高而且非常实用

七夕又被称为“乞巧节”&#xff0c;相传这一天是牛郎织女一年一度的相会日&#xff0c;所以在这个浪漫的节日里&#xff0c;很有多的恋人也会不远万里来相见&#xff0c;在这个浪漫的日子里&#xff0c;送礼物是表达心意和爱意的重要方式&#xff0c;那么&#xff0c;面对琳琅…

前端练手小项目--自定义时间(html+css+js)

自定义时间 写文章的因 关于要写这篇文章的原因 是记录在工作上遇到的困难需求&#xff0c;是希望能给大家提供一些解决问题的思路 接下来我描述这个需求的多样性&#xff0c;难点在哪。 勾选勾选框开始时间与结束时间默认显示昨天与今天。取消勾选框开始时间与结束时间清空。…

element+vue 表格行拖拽功能

解决方案 使用 sortable.js 步骤一&#xff1a; 安装 npm install vuedraggable步骤二&#xff1a;引入 import Sortable from sortablejs;步骤三&#xff1a; el-table 添加row-key属性&#xff0c;外层包一层 sortableDiv <div class"sortableDiv"> 拖…

IDEA【java.sql.SQLSyntaxErrorException: ORA-00904: “P“.“PRJ_NO“: 标识符无效】

IDEA报错如下&#xff1a; 2023-08-17 11:26:15.535 ERROR [egrant-biz,b48324d82fe23753,b48324d82fe23753,true] 24108 --- [ XNIO-1 task-1] c.i.c.l.c.RestExceptionController : 服务器异常org.springframework.jdbc.BadSqlGrammarException: ### Error queryin…

Docker 的基本概念和优势,在应用程序开发中的实际应用。

Docker是一个开源的容器化平台&#xff0c;让开发者能够轻松地打包、运输和运行应用程序。其基本概念包括&#xff1a; 镜像(Image)&#xff1a;一个镜像是一个只读的软件包&#xff0c;它包含了运行应用所需的所有代码、库文件、环境变量和配置文件等。 容器(Container)&…