数据结构之顺序表(java版)

目录

一.线性表

1.1线性表的概念

二.顺序表 

2.1顺序表的概念

2.2顺序表的实现

1.顺序表的接口

1.2顺序表的功能实现

1.顺序表初始化

2.新增元素功能:

3.清空顺序表是否为空&&获取顺序表长度&&打印顺序表:

4.判断是否包含某个元素&&查找某个元素的对应位置

5.在指定位置新增元素

6.获取pos位置的元素&&给pos位置的元素值设为value

7.删除第一次出现关键字key

2.3顺序表完整代码 

三.java中的ArrayList


一.线性表

1.1线性表的概念

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

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

本章我们主要讲的是顺序表。


二.顺序表 

2.1顺序表的概念

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

2.2顺序表的实现

1.顺序表的接口

有了接口,可以实现代码的复用。

package MyArraylistto;

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();
}

1.2顺序表的功能实现

首先,我们需要创建一个类并且实现接口中的方法。

MyArraylistf.java

1.顺序表初始化

在此之前,我们需要为顺序表开辟一定的空间内存。

 private int[] elems; // 用于存储数组元素的内部数组
    private int size; // 表示当前数组中元素的数量
     public MyArraylistf()
    {
        elems = new int[10]; // 初始化内部数组 elems,容量为10
        size = 0; // 将数组元素数量初始化为0
    }
    
2.新增元素功能:

我们在插入元素之前需要先判断我们所提供的内存是否已经用完了,如果用完了,我们可以使用Arrays.copyOf(原数组,开辟的空间大小).进行扩容。在插入数据元素后,我们需要让size+1。如下

  public  void add(int data)
    {
        if(size== elems.length){
            elems= Arrays.copyOf(elems,2*elems.length);
        }
        elems[size]=data;
        this.size++;
    }
3.清空顺序表是否为空&&获取顺序表长度&&打印顺序表:

1.清空顺序表长度:我们直接让size置为空。

2.获取顺序表长度:我们直接返回size的大小即可。

 public void clear(){//清空顺序表
        this.size=0;
    }
    public int size(){//返回顺序表元素个数
        return this.size;
    }
public void display(){
        for(int i=0;i<this.size;i++){
            System.out.print(elems[i]+" ");
        }
        System.out.println();
    }
4.判断是否包含某个元素&&查找某个元素的对应位置

判断是否包含某个元素,只需要遍历一遍顺序表即可,如果存在返回true,反之,返回false.

查找元素的位置,也是遍历一遍顺序表,找到返回对应下标即可。

  // 判定是否包含某个元素
    public boolean contains(int toFind){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toFind){
                return true;
            }
        }
        return false;
    }
    // 查找某个元素对应的位置
    public int indexOf(int toFind){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toFind){
                return i;
            }
        }
        return -1;
    }
5.在指定位置新增元素

我们在指定位置新增元素时,需要考虑:

1.插入的位置是否合法,如果小于0或者大于顺序表的最大长度,则抛出异常。

2.位置没有问题,那就需要判断顺序表是否已满,如果满了,进行扩容。

3.我们需要将pos位置以后的数据全部后移以为,才能进行插入。

   /* 检查给定的位置是否合法。
     * 如果位置小于0或大于当前数组大小,则抛出PosNotlegalException异常。
     * @param pos 要检查的位置
     * @throws PosNotlegalException 如果位置不合法,则抛出此异常
     */
    private void checkPos(int pos)throws PosNotlegalException{
        if(pos<0||pos>size){
            throw new PosNotlegalException("位置不合法");
        }
    }

    /**
     * 在指定的位置插入一个元素。
     * 首先会检查位置是否合法,然后将元素插入到指定位置,后续元素依次后移。
     * 如果数组已满,则会自动扩展数组大小。
     * @param pos 插入元素的位置
     * @param data 要插入的元素值
     */
    public void add(int pos, int data){
        // 判断位置是否合法
        try{
            checkPos(pos);
        }catch (PosNotlegalException e){
            e.printStackTrace();
        }
        // 检查顺序表是否已满,若满则扩展一倍容量
        if(size== elems.length){
            elems= Arrays.copyOf(elems,2*elems.length);
        }
        // 将插入位置之后的元素依次后移
        for(int i=size;i>pos;i--){
            elems[i]=elems[i-1];
        }
        // 在指定位置插入元素
        elems[pos]=data;
        // 更新数组大小
        size++;
    }
6.获取pos位置的元素&&给pos位置的元素值设为value

1.获取pos位置的元素:我们严谨一点,需要考虑pos是否合法,不合法抛出异常。

2.给pos位置的值设为value:我们与上相同,判断完,直接让pos位置的值改为value。 

 // 获取 pos 位置的元素
    public int get(int pos){
        try {
            checkPos(pos);
        }catch(PosNotlegalException e){
            e.printStackTrace();
        }
        return elems[pos];
    }
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value){
        try {
            checkPos(pos);
        }catch(PosNotlegalException e){
            e.printStackTrace();
        }
        elems[pos]=value;
    }
7.删除第一次出现关键字key

我们这里可以采用双层遍历的方式进行删除。

在外循环遍历的时候,如果数组中的元素与key相同,则进入内循环,将i位置的数据进行覆盖,我们需要遍历size-1次。

扩展:如果要删除所有出现key的元素,我们将return去掉即可

  /**
     * 删除数组中第一次出现的指定元素。
     * @param toRemove 需要删除的元素。
     */
    public void remove(int toRemove){
        // 遍历数组,寻找第一个匹配的元素
        for(int i=0;i<this.size;i++){
            if(elems[i]==toRemove){
                // 将找到元素后的元素依次向前移动
                for(int j=i;j<this.size-1;j++){
                    elems[j]=elems[j+1];
                }
                // 调整数组大小,表示已删除一个元素
                size--;
                return;
            }
        }
    }

   //删除数组中出现toRemove的全部元素
 public void removeAll(int toRemove){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toRemove){
                for(int j=i;j<this.size-1;j++){
                    elems[j]=elems[j+1];
                }
                size--;
            }
        }
    }

至此,我们把接口中的方法全部进行了实现。我们可以在main函数中进行测试一下。

2.3顺序表完整代码 

测试类:TTest.java

package MyArraylistto;

public class TTest {
    public static void main(String[] args) {
        MyArraylistf list = new MyArraylistf();
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(1);
        list.add(2);
        list.add(2,2);
        list.display();
        System.out.println("===========");
        list.removeAll(2);
        list.display();

    }
}

顺序功能实现:MyArraylistf.java

package MyArraylistto;

import java.util.Arrays;

public class MyArraylistf implements IList{
    /**
     * MyArraylistf 类用于实现一个简单的数组列表。
     * 该类内部使用整型数组存储元素,并且能够动态调整数组大小。
     */
    private int[] elems; // 用于存储数组元素的内部数组
    private int size; // 表示当前数组中元素的数量

    /**
     * MyArraylistf 构造函数。
     * 初始化内部数组 elems 为长度为 10 的整型数组,并将 size 设置为 0。
     */
    public MyArraylistf()
    {
        elems = new int[10]; // 初始化内部数组 elems,容量为10
        size = 0; // 将数组元素数量初始化为0
    }
    public  void add(int data)
    {
        if(size== elems.length){
            elems= Arrays.copyOf(elems,2*elems.length);
        }
        elems[size]=data;
        this.size++;
    }

    /**
     * 检查给定的位置是否合法。
     * 如果位置小于0或大于当前数组大小,则抛出PosNotlegalException异常。
     * @param pos 要检查的位置
     * @throws PosNotlegalException 如果位置不合法,则抛出此异常
     */
    private void checkPos(int pos)throws PosNotlegalException{
        if(pos<0||pos>size){
            throw new PosNotlegalException("位置不合法");
        }
    }

    /**
     * 在指定的位置插入一个元素。
     * 首先会检查位置是否合法,然后将元素插入到指定位置,后续元素依次后移。
     * 如果数组已满,则会自动扩展数组大小。
     * @param pos 插入元素的位置
     * @param data 要插入的元素值
     */
    public void add(int pos, int data){
        // 判断位置是否合法
        try{
            checkPos(pos);
        }catch (PosNotlegalException e){
            e.printStackTrace();
        }
        // 检查顺序表是否已满,若满则扩展一倍容量
        if(size== elems.length){
            elems= Arrays.copyOf(elems,2*elems.length);
        }
        // 将插入位置之后的元素依次后移
        for(int i=size;i>pos;i--){
            elems[i]=elems[i-1];
        }
        // 在指定位置插入元素
        elems[pos]=data;
        // 更新数组大小
        size++;
    }

    // 获取 pos 位置的元素
    public int get(int pos){
        try {
            checkPos(pos);
        }catch(PosNotlegalException e){
            e.printStackTrace();
        }
        return elems[pos];
    }
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value){
        try {
            checkPos(pos);
        }catch(PosNotlegalException e){
            e.printStackTrace();
        }
        elems[pos]=value;
    }
    //删除第一次出现的关键字key
    public void remove(int toRemove){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toRemove){
                for(int j=i;j<this.size-1;j++){
                    elems[j]=elems[j+1];
                }
                size--;
                return;
            }
        }
    }
    
    
    public void removeAll(int toRemove){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toRemove){
                for(int j=i;j<this.size-1;j++){
                    elems[j]=elems[j+1];
                }
                size--;
            }
        }
    }
    // 判定是否包含某个元素
    public boolean contains(int toFind){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toFind){
                return true;
            }
        }
        return false;
    }
    
   
    
    // 查找某个元素对应的位置
    public int indexOf(int toFind){
        for(int i=0;i<this.size;i++){
            if(elems[i]==toFind){
                return i;
            }
        }
        return -1;
    }
    public void clear(){//清空顺序表
        this.size=0;
    }
    public int size(){//返回顺序表元素个数
        return this.size;
    }

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

接口:IList.java 

package MyArraylistto;

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();
}

三.java中的ArrayList 

在集合框架中,ArrayList是一个普通的类,实现了List接口,具体框架如下:

 说明

1. ArrayList是以泛型方式实现的,使用时必须要先实例化

2. ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问 

3. ArrayList实现了Cloneable接口,表明ArrayList是可以clone的

4. ArrayList实现了Serializable接口,表明ArrayList是支持序列化的

5. 和Vector不同,ArrayList不是线程安全的,在单线程下可以使用,在多线程中可以选择Vector或者 CopyOnWriteArrayList

6. ArrayList底层是一段连续的空间,并且可以动态扩容,是一个动态类型的顺序表

 3.1ArrayList的使用

java中所提供的方法在ArrayList (Java 平台 SE 8 ) (oracle.com)可进行查看。

四.顺序表的缺陷

1.ArrayList底层使用连续的空间,任意位置的插入或删除元素时,需要将该位置后序元素整体向前或者向后移动,时间复杂度为O(N)。

2.扩容的时候需要申请新的空间,拷贝数据,释放旧空间,会有不小的损耗。

3.扩容一般是呈2倍的增长,所以一定会有空间的浪费。例如,你开辟了50的空间,等满了以后扩容到100,这时再利用10个空间,但后面的空间没有使用,就浪费了45个数据空间。

但是我们使用链表不会有这样的问题。

链表在插入数据的时候是生成一个个数据空间,通过指针连接起来,这样就不会造成空间的浪费。

同时,链表在插入和删除数据的效率比顺序表快。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

关于开设YOLOv8专栏及更新内容的一些说明

​ 专栏介绍&#xff1a;YOLOv9改进系列 | 包含深度学习最新创新&#xff0c;助力高效涨点&#xff01;&#xff01;&#xff01; 专栏介绍 ⭐后期更新包含模块、卷积、检测头、损失等改进,目前已有70&#xff01;现在入手仅$ 69.9&#xff0c;早入早发论文&#xff01;⭐ ⭐…

【前端技术】HTML基础入门篇

1.1 HTML简介 ​ HTML&#xff08;HyperText Markup Language&#xff1a;超文本标记语言&#xff09;是一种标识性的语言。它包括一系列标签&#xff0e;通过这些标签可以将网络上的文档格式统一&#xff0c;使分散的Internet资源连接为一个逻辑整体。HTML文本是由HTML命令组…

uView u-parse 在nvue页面中无作用踩坑

问题起因&#xff1a; 在uni-app开发的app nvue页面中有需要回显渲染字符串形式的富文本内容 但使用v-html和uniapp的rich-text组件都无法起到作用&#xff0c;就想到了使用uView中u-parse进行尝试。 uView我是使用uniApp插件市场导入的方式将插件导入项目的uni_modules中 …

2024年教你学浪视频抓取#小浪助手

在2024年&#xff0c;学浪平台已经成为学习者们追逐知识、获取学习资源的热门平台之一。然而&#xff0c;尽管学习平台提供了丰富多样的学习内容&#xff0c;但有时候我们还是希望能够将这些学习资源下载下来&#xff0c;以便随时随地进行学习。那么&#xff0c;如何学习学浪视…

【layoutlmv3推理】无法识别的pdf使用ocr识别代码demo实例

目录 前情提要一、安装依赖1、直接安装的依赖2、需要编译的依赖1&#xff09;Leptonica2&#xff09;icu3&#xff09;Tesseract 3、需要自行配置的依赖 二、模型下载三、更改transformers源码四、加载光学字符识别语言包五、运行代码 前情提要 在做pdf转文本时&#xff0c;发…

用于割草机器人,商用服务型机器人的陀螺仪

介绍一款EPSON推出适用于割草机器人&#xff0c;商用服务型机器人的高精度陀螺仪模组GGPM61&#xff0c;具体型号为GGPM61-C01。模组GGPM61是一款基于QMEMS传感器的低成本航向角输出的传感器模组&#xff0c;它可以输出加速度、角速度及姿态角等信息&#xff0c;为控制机器人运…

航空业微服务架构中台的构建与实践

随着航空业的快速发展&#xff0c;航空公司需要面对更加复杂的业务环境和客户需求。在这样的背景下&#xff0c;构建一个稳健、高效的微服务架构中台成为了航空公司的当务之急。本文将探讨航空业微服务架构中台的设计理念、关键技术以及实践经验&#xff0c;帮助航空公司构建具…

「Java开发指南」如何利用MyEclipse启用Spring DSL?(二)

本教程将引导您通过启用Spring DSL和使用Service Spring DSL抽象来引导Spring和Spring代码生成项目&#xff0c;本教程中学习的技能也可以很容易地应用于其他抽象。在本教程中&#xff0c;您将学习如何&#xff1a; 为Spring DSL初始化一个项目创建一个模型包创建一个服务和操…

面向多源异质遥感影像地物分类的自监督预训练方法

源自&#xff1a;测绘学报 作者&#xff1a;薛志祥, 余旭初, 刘景正, 杨国鹏, 刘冰, 余岸竹, 周嘉男, 金上鸿 摘 要 近年来,深度学习改变了遥感图像处理的方法。由于标注高质量样本费时费力,标签样本数量不足的现实问题会严重影响深层神经网络模型的性能。为解决这一突出矛盾…

将本地项目推送至gitlab仓库

1. gitlab上新建一个空白项目 gitlab上点击new project按钮&#xff0c;新建一个项目 新建空白项目 项目名称与本地新建项目名称相同&#xff0c;其余根据具体需要选择 2. 初始化本地仓库并commit项目 进入本地项目根目录下&#xff0c;右击 git bash here打开命令窗口 初始化…

MappedStatement解析流程

前言 之前写了一篇博文&#xff0c;介绍了mybatis的解析过程&#xff0c;其中mapper标签只演示了如何使用&#xff0c;这篇博文我们来探究mapper标签解析流程 源码解析 核心方法入口 引入mapper方式 使用相对于类路径的资源引用使用完全限定资源定位符&#xff08;URL&…

“五之链”第十六期沙龙活动在呆马科技成功举办

2024年4月19日&#xff0c;由临沂呆码区块链网络科技有限公司&#xff08;呆马科技&#xff09;承办的第十六期“五之链”物流主题沙龙活动成功举办。此次活动邀请了政府相关部门、知名科研院所、物流企业等20余家单位参与&#xff0c;共同探讨物流数据要素流通与智能应用的发展…

新版ONENET(2024/4/24)通过view3.0可视化保姆级教程(一学就会)附效果图

⏩ 大家好哇&#xff01;我是小光&#xff0c;想要成为系统架构师的嵌入式爱好者。 ⏩上一篇是STM32通过ESP8266连接最新版的ONENET&#xff0c;成功将数据上传之后&#xff0c;本篇文章使用ONENET的view3.0可视化对数据进行可视化做一个详细教程。 ⏩感谢你的阅读&#xff0c;…

AnaTraf网络流量分析仪:实时分析工具助您优化网络架构

导言&#xff1a; 在如今高度互联的数字时代&#xff0c;网络流量分析成为了企业和组织必备的工具之一。AnaTraf网络流量分析仪作为一款高性能的实时网络流量分析工具&#xff0c;不仅能够帮助用户进行全流量回溯分析、网络流量监控和网络性能分析&#xff0c;更可以快速排除网…

两天速通阿里

感觉这一周太梦幻了&#xff0c;就像一个梦&#xff0c;很不真实~~~ 感觉这个暑期&#xff0c;我的运气占了99成&#xff0c;实力只有百分之一 4.15上午 腾讯csig 腾讯云部门&#xff0c;面完秒进入复试状态 4.16下午 美团优选供应链部门&#xff0c;4.18上午发二面 4.17晚上 阿…

C#基础|属性Property之读写特性和经典总结

哈喽&#xff0c;你好&#xff0c;我是雷工。 本节学习属性特性——控制读写操作&#xff0c;以下为学习笔记。 01 只读属性 写法1&#xff1a;直接去掉set方法&#xff0c;可以在定义的时候初始化。 示例&#xff1a; public string CourseName{get&#xff1b;}“雷工笔记…

2024年学浪提取视频#小浪助手

2024年&#xff0c;学习视频已经成为人们获取知识和提升技能的重要途径&#xff0c;而学浪视频平台以其丰富多样的学习资源备受瞩目。然而&#xff0c;有时我们可能只需要其中的一小部分内容&#xff0c;而不想将整个视频都下载下来。在这个时候&#xff0c;小浪助手作为一款强…

软件无线电系列——Nyquist采样定理

本节目录 一、Nyquist采样定理 1、Nyquist采样定理的定义 2、Nyquist采样定理的证明本节内容 一、Nyquist采样定理 如果对某一时间连续信号进行采样&#xff0c;当采样速率达到一定数值时&#xff0c;就可以根据这些采样值准确地确定原信号。 1、Nyquist采样定理的定义 何为Ny…

这操作真牛!APT杜绝软件包被篡改

0x00 简介 我们介绍了传统包管理器、新型包管理器的工作方式&#xff0c;其中用了大篇幅介绍 APT 包管理器&#xff0c;但是没有对安全人员比较关心的软件包校验问题进行介绍 0x01 大众疑问环节 这部分主要是从常规 Linux 使用者的视角&#xff0c;提出一些平时工作过程中的…

到底什么是爬虫

1. 引言 在数据驱动的世界里&#xff0c;网络爬虫&#xff08;Web Crawling&#xff09;技术扮演着获取和处理网上数据的关键角色。无论是为了数据分析、机器学习项目的数据集构建还是简单地监测网页变化&#xff0c;学习如何创建一个基本的网页爬虫可以大大提升你的工作效率和…