数据结构----线性表、顺序表、模拟实现顺序表

news2024/10/1 19:33:00

文章目录

  • 1. 线性表
  • 2. 顺序表
  • 3. 模拟实现顺序表

1. 线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,指具有相同数据类型的元素按照一定的顺序排列的数据结构,其中每个元素都有唯一的前驱元素和后继元素(除了第一个元素没有前驱,最后一个元素没有后继),常见的线性表:顺序表、链表、栈、队列…
在这里插入图片描述

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

2. 顺序表

顺序表是一种线性表的存储结构,它是由一组地址连续的存储单元依次存储线性表中的元素,元素之间的逻辑关系和物理关系是一致的。顺序表可以通过数组来实现,在数组上完成数据的增删查改。

顺序表的主要特点是:

  • 元素之间的逻辑关系和物理关系是一致的,即顺序表中的元素在内存中是连续存储的。
  • 可以通过下标直接访问和修改元素,因此支持随机访问。
  • 具有固定的容量,需要预先分配足够的内存空间来存储元素,如果需要动态调整大小,可能需要重新分配内存空间并进行元素的复制。
  • 元素的插入和删除操作可能需要移动其他元素来保持顺序,因此效率较低。

顺序表在实际应用中有着广泛的应用,例如数组就是一种顺序表的实现方式。在计算机科学中,顺序表也是一种重要的数据结构,用于存储和操作线性表中的元素。

3. 模拟实现顺序表

下面是我写的一个基于数组实现的顺序表(MyArrayList)的完整代码,包含了每个方法的实现:

【IList.clss】:
模拟List接口,里面记录了MyArrayList需要实现的方法

public interface IList {
    // 新增元素,默认在数组最后新增
    public void add(int data);

    // 在 pos 位置新增元素
    public void add(int pos, int data);

    // 判定是否包含某个元素
    public boolean contains(int toFind);

    // 查找某个元素对应的位置
    public int indexOf(int toFind);

    // 获取 pos 位置的元素
    public int get(int pos);

    // 给 pos 位置的元素设为 value
    public void set(int pos, int value);

    //删除第一次出现的关键字key
    public void remove(int toRemove);

    // 获取顺序表长度
    public int size();

    // 清空顺序表
    public void clear();

    // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
    public void display();
}

【MyArrayListEmpty.clss】:
自定义异常数组为空异常(运行时异常)

public class MyArrayListEmpty extends RuntimeException{
    public MyArrayListEmpty(String msg) {
        super(msg);
    }
}

【PositionIllegal.clss】:
自定义异常数组下标非法(运行时异常)

public class PositionIllegal extends RuntimeException{
    public PositionIllegal(String msg) {
        super(msg);
    }
}

【PositionOutOfBounds .clss】:
自定义异常数组访问元素时下标越界(运行时异常)

public class PositionOutOfBounds extends RuntimeException {
    public PositionOutOfBounds(String msg) {
        super(msg);
    }
}

【MyArrayList.class】:

public class MyArrayList implements IList {
    int[] elements;//用来存放数据元素
    int usedSize;//代表当前顺序表中的有效数据个数

    public static final int DEFAULT_SIZE = 2;//默认的数组中的数据的个数

    // 默认构造方法
    public MyArrayList() {
        this.elements = new int[DEFAULT_SIZE];//默认初始大小
    }

    // 将顺序表的底层容量设置为initCapacity
    public MyArrayList(int initCapacity) {
        this.elements = new int[initCapacity];//自定义大小
    }

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

    @Override
    public void add(int data) {
        //扩容
        checkCapacity();
        //添加数组
        this.elements[this.usedSize] = data;
        //有效数据个数加一
        this.usedSize++;
    }

    private boolean isFull() {
        //1.检查数组是否满了
        if (this.usedSize == elements.length) {
            return true;
        }
        return false;
    }

    private void checkCapacity() {
        //2.检查数组容量并进行扩容
        if (isFull()) {
            // 数组容量扩大二倍
            this.elements = Arrays.copyOf(elements, 2 * (this.elements.length));
        }
    }

    @Override
    public void add(int pos, int data) {
        //1.检查数组元素下标是否合法
        checkPositionIllegalOnAdd(pos);
        //2.检查数组的容量
        checkCapacity();
        //3.将数据存放在对应要存放的位置
        for (int i = this.usedSize - 1; i >= pos; i++) {
            this.elements[i + 1] = this.elements[i];
        }
        this.elements[pos] = data;
        this.usedSize++;
    }


    @Override
    public boolean contains(int toFind) {
        //1.判断数组是否为空
        isEmpty();
        //2.判断数组中是否含有该元素
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elements[i] == toFind) {
                return true;
            }
        }
        return false;
    }


    @Override
    public int indexOf(int toFind) {
        //1.判断数组是否为空
        isEmpty();
        //2.判断数组中是否含有该元素
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elements[i] == toFind) {
                return i;
            }
        }
        //3.数组中不含有该元素,返回值为-1
        return -1;
    }


    @Override
    public int get(int pos) {
        //检查数组下标是否越界
        checkPositionGetAndSet(pos);
        //判断数组是否为空
        isEmpty();
        //得到下标对应的值
        int ret = this.elements[pos];
        return ret;
    }


    @Override
    public void set(int pos, int value) {
        //检查数组下标是否越界
        checkPositionGetAndSet(pos);
        //判断数组是否为空
        isEmpty();
        //设置下标对应的值
        this.elements[pos] = value;
    }

    @Override
    public void remove(int toRemove) {
        //获取要删除的元素对应的下标
        int index = indexOf(toRemove);
        //判断下标
        if (index != -1) {
            //将index之后的所有元素向前移动一位
            for (int i = index; i < this.usedSize - 1; i++) {
                this.elements[i] = this.elements[i + 1];
            }
            //删除元素之后,数组计数器减一
            this.usedSize--;
        }
    }

    @Override
    public int size() {
        return this.usedSize;
    }

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

    private void checkPositionIllegalOnAdd(int pos) throws PositionIllegal {
        //存放数据的合法位置为 :0 ~ usedSize
        if (pos < 0 || pos > this.usedSize) {
            throw new PositionIllegal("数组的下标" + pos + "不合法");
        }
    }

    private void checkPositionGetAndSet(int pos) {
        if (pos < 0 || pos >= this.usedSize) {
            throw new PositionOutOfBounds("数组下标" + pos + "越界");
        }
    }

    public void isEmpty() {
        if (this.usedSize == 0) {
            throw new MyArrayListEmpty("该数组为空");
        }
    }
}

【讲解部分一】:

    private void checkCapacity() {
        //2.检查数组容量并进行扩容
        if (isFull()) {
            // 数组容量扩大二倍
            this.elements = Arrays.copyOf(elements, 2 * (this.elements.length));
        }
    }

Arrays.copyOf ( ) 方法是Java中用于复制数组的方法。它可以复制指定数组的所有元素到一个新数组中,并返回新数组。 Arrays.copyOf ( ) 方法有两个参数:源数组和目标数组的长度。

下面是 Arrays.copyOf ( ) 方法的语法:

public static <T> T[] copyOf(T[] original, int newLength)

其中,original是源数组,newLength是目标数组的长度。返回的数组类型与源数组类型相同。需要注意的是, Arrays.copyOf ( ) 方法会根据目标数组的长度进行复制。如果目标数组长度小于源数组长度,复制结果将截取源数组的前部分元素;如果目标数组长度大于源数组长度,复制结果将在末尾填充默认值 0 。

【讲解部分二】:

public boolean contains(int toFind) {
        //1.判断数组是否为空
        isEmpty();
        //2.判断数组中是否含有该元素
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elements[i] == toFind) {
                return true;
            }
        }
        return false;
    }

如果里面的每一个元素都是引用类型,需要使用equals()来进行比较,如果是自定义类型,还需要自己覆盖equals()方法。

public boolean contains(int toFind) {
        //1.判断数组是否为空
        isEmpty();
        //2.判断数组中是否含有该元素
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elements[i].equals(toFind)) {
                return true;
            }
        }
        return false;
    }

【讲解部分三】:

  public void remove(int toRemove) {
        //获取要删除的元素对应的下标
        int index = indexOf(toRemove);
        //判断下标
        if (index != -1) {
            //将index之后的所有元素向前移动一位
            for (int i = index; i < this.usedSize - 1; i++) {
                this.elements[i] = this.elements[i + 1];
            }
            //删除元素之后,数组计数器减一
            this.usedSize--;
        }
    }

如果里面的每一个元素都是引用类型,需要对最后一个元素设置为null,如果不这样做,那么你对最后一个对象的引用将遗留而造成内存泄漏。

【讲解部分四】:

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

如果数组中每一个元素都是引用类型,将this.usedSize = 0;时,会发生内存泄露,原因是JVM只有当对象没有被引用时,才会进行对象回收,this.usedSize = 0;时并没将元素置为null,顺序表仍然引用对象,JVM无法进行回收。

方式一:

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

较为暴力,不推荐

方式二:

  public void clear() {
        for(int i = 0;i < this.usedSize;i++){
        	this.element[i] = null;
        }
        this.usedSize = 0;
    }

比较建议,使用垃圾回收器(GC)进行回收

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

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

相关文章

Python笔记12-多线程、网络编程、正则表达式

文章目录 多线程网络编程正则表达式 多线程 现代操作系统比如Mac OS X&#xff0c;UNIX&#xff0c;Linux&#xff0c;Windows等&#xff0c;都是支持“多任务”的操作系统。 进程&#xff1a; 就是一个程序&#xff0c;运行在系统之上&#xff0c;那么便称之这个程序为一个运…

17β-Estradiol high sensitivity ELISA kit

高灵敏ELISA试剂盒&#xff0c;可检测到低至14 pg/ml的17β-雌二醇 雌二醇(estradiol) 是由卵巢内卵泡的颗粒细胞分泌的类固醇激素&#xff0c;是主要的雌激素&#xff0c;负责调节女性特征、附属性器官的成熟和月经-排卵周期&#xff0c;促进乳腺导管系统的产生&#xff0c;有…

全双工通信协议:WebSocket

全双工通信协议&#xff1a;WebSockets 前言何时使用WebSocketsWebSocket APITextWebSocketHandlerWebSocketConfigurerWebSocket握手配置服务器允许的来源心跳包Java WebSocket API案例一&#xff1a;前端发送消息并接收后端响应案例二&#xff1a;模拟后端向前端推送消息案例…

【DeepLearning-2】预归一化(Pre-Normalization)策略

2.1层归一化&#xff08;Layer Normalization&#xff09;在 PreNorm 类中的数学原理&#xff1a; 2.2代码实现&#xff1a; class PreNorm(nn.Module):def __init__(self, dim, fn):super().__init__()self.norm nn.LayerNorm(dim)self.fn fn def forward(self, x, **kwar…

SpringBoot-多数据源切换和事物处理(免费)

作者原始文章: SpringBoot-多数据源切换和事物处理 最新内容和改动请看上面的文章 安装 <dependency><groupId>com.gitee.huanminabc</groupId><artifactId>dynamic-datasource</artifactId><version>1.0.3-RELEASE</version> <…

初识SQL注入

目录 注入攻击 SQL注入 手工注入 Information_schema数据库 自动注入 介绍一下这款工具&#xff1a;sqlmap 半自动注入 前面给大家通过学习练习的方式将XSS攻击的几种形式和一些简单的靶场和例题的演示&#xff0c;从本篇开始我将和小伙伴们通过边复习、边练习的方式来进…

MongoDB系列之一文总结索引

概述 分类 索引的分类&#xff1a; 按照索引包含的字段数量&#xff0c;可分为单键索引&#xff08;单字段索引&#xff09;和组合索引&#xff08;联合索引、复合索引&#xff09;按照索引字段的类型&#xff0c;可以分为主键索引和非主键索引按照索引节点与物理记录的对应…

QT 实现自动生成小学两位数加减法算式

小学生加减法训练 QT实现–自动生成两位数加减法算式&#xff0c;并输出txt文件 可以copy到word文件&#xff0c;设置适当字体大小和行间距&#xff0c;带回家给娃做做题 void MainWindow::test(int answerMax, int count) {// 创建一个随机数生成器QRandomGenerator *gener…

宝塔面板SRS音视频TRC服务器启动失败

首先&#xff0c;查找原因 1.先看srs服务在哪 find / -type f -name srs 2>/dev/null运行结果&#xff1a; /var/lib/docker/overlay2/5347867cc0ffed43f1ae24eba609637bfa3cc7cf5f8c660976d2286fa6a88d2b/diff/usr/local/srs/objs/srs /var/lib/docker/overlay2/5347867…

展厅设计更好的方法

一、与公司形象契合 在展厅规划时必定要留意公司的LOGO、主色调&#xff0c;以及企业文明。在展现时使用丰满的展厅规划传达出企业的理念。而在功用设置上&#xff0c;应当考虑内涵功用&#xff0c;从展厅作业人员的视点动身&#xff0c;为展厅作业人员提供杰出的环境&#xff…

L1-093 猜帽子游戏(Java)

宝宝们在一起玩一个猜帽子游戏。每人头上被扣了一顶帽子&#xff0c;有的是黑色的&#xff0c;有的是黄色的。每个人可以看到别人头上的帽子&#xff0c;但是看不到自己的。游戏开始后&#xff0c;每个人可以猜自己头上的帽子是什么颜色&#xff0c;或者可以弃权不猜。如果没有…

菜鸡后端的前端学习记录

前言 记录一下看视频学习前端的的一些笔记&#xff0c;以前对Html、Js、CSS有一定的基础&#xff08;都认得&#xff0c;没用过&#xff09;&#xff0c;现在不想从头再来了&#xff0c;学学Vue框架&#xff0c;不定时更新&#xff0c;指不定什么时候就鸽了。。。。 Vue2 01…

elementui 表单 resetFields 方法不生效问题解决

问题 调用 elementui 官方提供的表单重置方法 resetFields 方法重置表单不生效&#xff0c;相信很多小伙伴都遇到过这个问题。 解决方法 检查代码看每个表单项的 prop 与 v-model 绑定的属性值命名是否相同&#xff0c;不相同的话就会导致 resetFields 方法不生效的问题&am…

「萌龙送宝」玉树芝兰定制红包封面免费发放

第二波红包封面&#xff0c;来了。 昨天晚上&#xff0c;我在公众号文章里免费发了 6000 份微信红包定制封面。根据 2022 年的经验&#xff0c;我原本以为这些红包怎么也得发个 12 小时&#xff0c;甚至是一天。但事实教育了我 —— 只用了半个小时&#xff0c;就发光了。 很多…

rabbitmq基础-java-1、快速入门

1、AMQP AMQP&#xff0c;即Advanced Message Queuing Protocol&#xff08;高级消息队列协议&#xff09;&#xff0c;一个提供统一消息服务的应用层标准高级消息队列协议&#xff0c;是应用层协议的一个开放标准&#xff0c;为面向消息的中间件设计&#xff0c;基于此协议的客…

Pygame之纯Python实现你好2024效果

Pygame之纯Python实现你好2024效果 前言&#xff1a; 对于某些指JavaScript与前端实现为Python实现你好2024效果的营销号实在看不下去了。无底线营销&#xff0c;还要私信拿源码&#xff0c;hhh 于是就有了以下代码&#xff1a; 运行前安装pygame pip install pygame运行效果…

apkpure下载Google Play中APP的APK安装包

比如Google Play上有个应用叫iSmart DV&#xff0c;想下载APK&#xff0c;怎么做呢 打开apkpure(https://apkpure.net/)&#xff0c;输入对应的app名称即可下载

Integer.valueOf方法详解

Integer.valueOf 是 Java 中 Integer 类的一个静态方法&#xff0c;它用于将给定的字符串或基本数据类型转换成一个 Integer 对象。 使用场景 从字符串转换&#xff1a;将字符串形式的数字转换为 Integer 对象。 Integer num Integer.valueOf("123");从基本数据类…

springboot druid数据库配置密码加密

1.使用的druid版本 <!-- 阿里数据库连接池 --> <dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-3-starter</artifactId><version>1.2.21</version> </dependency> 2.配置文件 # Spring配置 …

酷开科技 | 酷开系统全能基因 融合架构更多精彩

智能电视和智能电视操作系统早已不是新鲜事物&#xff0c;随着人们对智能电视的使用需求越来越多&#xff0c;一些消费者开始了探索电视的更多可能性&#xff0c;酷开科技通过对消费者群体的调研将酷开系统进行了创造性的升级&#xff0c;更强大的功能&#xff0c;让我们深切的…