基于数组实现的顺序表(SeqList)

news2024/11/27 16:46:19

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

它的详细定义如下:

顺序表是一种数据结构,用于存储一组具有相同数据类型的元素,并按照元素在内存中的顺序进行存储和访问。顺序表中的元素在内存中是连续存储的,通过元素的下标可以直接访问和修改元素的值。

顺序表是线性表的一种实现方式。线性表是指具有相同数据类型的元素按照一定的顺序排列的数据结构,其中每个元素都有唯一的前驱元素和后继元素(除了第一个元素没有前驱,最后一个元素没有后继)。线性表可以通过顺序表、链表、栈、队列等不同的数据结构来实现。

顺序表的主要特点是:

  • 元素的存储是连续的,可以通过下标直接访问和修改元素。
  • 具有固定的容量,需要预先分配足够的内存空间来存储元素。
  • 元素的插入和删除操作可能需要移动其他元素来保持顺序。

顺序表的隶属关系是属于线性表这个更广义的概念,同时也是线性表的一种具体实现方式。其他线性表的实现方式还包括链表、栈和队列等。不同的实现方式在存储结构和操作特性上有所差异,可以根据具体的需求选择合适的数据结构来实现线性表。

可能有人还是会有一点懵,顺序表到底隶属于什么?我们要怎么使用它?

这么说吧,顺序表可以是一个类,也可以是一个数据结构的实例。

作为一个类,顺序表可以被定义为一个具体的数据类型,其中包含了相关的属性和方法来实现顺序表的操作。这样的顺序表类可以通过实例化来创建具体的顺序表对象,并通过调用对象的方法来进行元素的插入、删除、查找等操作。(比如一会儿我们要来实现的这个顺序表)

另一方面,顺序表也可以被看作是线性表的一种实现方式,即通过顺序存储结构来实现线性表的操作。在这种情况下,顺序表可以被看作是线性表的一种具体实例,它满足线性表的特性,并提供了线性表的操作接口。

所以,顺序表既可以是一个类,也可以是一个数据结构的实例,它可以实现线性表的接口或者具有线性表的特性和操作。具体要看在哪个上下文中使用和定义顺序表。

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

public class MySeqList {
    private int[] array;  //用来存放数据元素
    private int size;  //代表当前顺序表中的有效数据个数

    private static final int DEFAUL_SIZE = 10 ; //一个默认的数据个数

    // 默认构造方法
    public MySeqList() {
        this.array = new int[DEFAUL_SIZE];
        //size 不初始化,默认为 0 .
    }

    // 将顺序表的底层容量设置为initCapacity
    public MySeqList(int initCapacity) {
        this.array = new int[initCapacity];
        this.size = 0;
    }

    // 新增元素,默认在数组最后新增
    public void add(int data) {
        if (this.size == this.array.length) {
            resizeArray();
        }
        this.array[this.size] = data;
        this.size++;
    }

    // 在 pos 位置新增元素
    //先要挪动数据------从后往前挪动
    public void add(int pos, int data) throws IndexOutOfBoundsException {
        if (pos < 0 || pos > this.size) {
            throw new IndexOutOfBoundsException("Invalid position: " + pos);
        }
        //如果是满的,要先进行扩容
        if (this.size == this.array.length) {
            resizeArray();
        }
        for (int i = this.size; i > pos; i--) {
            this.array[i] = this.array[i - 1];
        }
        this.array[pos] = data;
        this.size++;
    }

    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i < this.size; i++) {
            if (this.array[i] == toFind) {
                return true;
            }
        }
        //如果找的是一个引用类型,还可以用等号吗?
        //equals()返回值是 true、false
        //comparaTo 返回的是整型,比较大小
        return false;
    }

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

    // 获取 pos 位置的元素
    public int get(int pos) throws IndexOutOfBoundsException {
        if (pos < 0 || pos >= this.size) {
            throw new IndexOutOfBoundsException("Invalid position: " + pos);
        }
        return this.array[pos];
    }

    // 给 pos 位置的元素设为 value
    // 可以理解为更新
    public void set(int pos, int value) throws IndexOutOfBoundsException {
        if (pos < 0 || pos >=this.size) {
            throw new IndexOutOfBoundsException("Invalid position: " + pos);
        }
        array[pos] = value;
    }

    // 删除第一次出现的关键字 key
    public void remove(int toRemove) {
        int index = indexOf(toRemove);
        if (index != -1) {
            for (int i = index; i < this.size - 1; i++) {
                this.array[i] = this.array[i + 1];
            }
            this.size--;
        }
    }

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

    // 清空顺序表
    public void clear() {
        this.size = 0;
    }

    // 打印顺序表
    public void display() {
        for (int i = 0; i < this.size; i++) {
            System.out.print(this.array[i] + " ");
        }
        //换行
        System.out.println();
    }

    // 内部方法:数组扩容
    private void resizeArray() {
        int[] newArray = new int[this.array.length * 2];
        System.arraycopy(this.array, 0, newArray, 0, this.size);
        this.array = newArray;
    }
}

class IndexOutOfBoundsException extends Exception{
    public IndexOutOfBoundsException() {
        super("Invalid position");
    }

    public IndexOutOfBoundsException(String message) {
        super(message);
    }

}

当然,这里 add(int data) 和 resizeArray() 还可以运用 Arrays 类的 copyOf () 改写为这样:

    public boolean isFull(){
        if(this.size==this.array.length){
            return true;
        }
        return false;
    }
    public void add2(int data) {
        if (isFull()) {
            this.array = Arrays.copyOf(this.array,2*this.array.length);
        }
        this.array[this.size] = data;
        this.size++;
    }

复习以下我们的 Arrays.copyOf ( ) 方法:

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

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

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

其中,original是源数组,newLength是目标数组的长度。返回的数组类型与源数组类型相同。

以下是一个示例,演示如何使用 Arrays.copyOf ( ) 方法复制数组:

import java.util.Arrays;

public class ArrayCopyExample {
    public static void main(String[] args) {
        int[] sourceArray = {1, 2, 3, 4, 5};
        int[] targetArray = Arrays.copyOf(sourceArray, sourceArray.length);

        System.out.println("Source Array: " + Arrays.toString(sourceArray));
        System.out.println("Target Array: " + Arrays.toString(targetArray));
        //别怀疑,输出的值是一样的
    }
}

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

哦,对了。你也可以把 “ 检查数组是否已满,需要扩容 ” 的代码单独提出来,形成一个新的方法。

还有,在清空顺序表这个方法里,如果里面的每一个元素都是引用类型,那么你需要一个一个的把往前覆盖的数据的原来位置置为 null 。

for(int i =0 ; i < this.size ; i++ )
{
    this.array [i]== this.array[i+1]; 
}
    this.array [this.size-1]==null; 
    this.size--;

如果不这样做,那么你对最后一个对象的引用将遗留而造成内存泄漏。

你是否发现,我们写出来的方法大多是一环套一环的,比如,先写了 indexOf( ) ,在 remove( ) 中就可以直接运用了。所以在开始写代码前,拿出一点时间来思考应该先完成哪一个方法是很有必要的。

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

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

相关文章

数据库【库,表操作】

目录 简单了解1.连接数据库服务器2.创建数据库3.创建表4.使用数据库5.数据库框架6.SQL的分类7.存储引擎 库操作1.创建数据库2.查看系统默认字符集以及校验规则3.查看数据库支持的字符集和校验规则4.查看数据库5.显示数据库语句6.删除数据库7.修改数据库8.备份和恢复9.查看连接情…

20 SQL——多表查询 (消除无效笛卡尔积)

create table dept(id int primary key auto_increment,name varchar(15))comment 部门;insert into dept(id, name) values (1,研发部),(2,市场部),(3,财务部),(4,销售部),(5,总经办),(6,人事部);create table staff (id int primary key auto_increment commentID,name …

【面试篇】Redis持久化面试题

文章目录 Redis持久化&#x1f64e;‍♂️面试官&#xff1a;什么是Redis持久化&#xff1f; AOF日志AOF日志原理&#x1f64e;‍♂️面试官&#xff1a;AOF日志是怎么工作的/AOF写入磁盘的流程&#xff1f;&#x1f64e;‍♂️面试官&#xff1a; 刚刚说到了Redis先执行写入的…

Discourse Math 插件

概述Discourse Math 使用 MathJax (默认) 或者 KaTeX 来让你在你的 Discourse 中使用数学公式。 仓库链接GitHub - discourse/discourse-math: Official MathJax support for Discourse Install Guide如何在 Discourse 中安装插件 这个插件是 Discourse 官方提供的插件&#x…

javascript基础一:Javscript数组的常用方法有哪些?

在日常开发中&#xff0c;我们对数组可以说操作最多&#xff0c;这里我们来整理下数组的一下最常用的方法 数组基本操作可以归纳为 增、删、改、查&#xff0c;需要留意的是哪些方法会对原数组产生影响&#xff0c;哪些方法不会 下面对数组常用的操作方法做一个归纳 一、基本…

ChatGPT国内免费使用的方法有哪些?

目录 一、ChatGpt是什么&#xff1f; 二、ChatGPT国内免费使用的方法&#xff1a; 第一点&#xff1a;电脑端 第二点&#xff1a;手机端 三、结语&#xff1a; 一、ChatGpt是什么&#xff1f; ChatGPt是美国OpenAI [1] 研发的聊天机器人程序 。更是人工智能技术驱动的自然语…

【C++数据结构】二叉搜索树的使用和模拟实现及其应用--K模型和KV模型

文章目录 一、二叉搜索树的概念二、二叉搜索树的操作及其实现(非递归)1.二叉搜索树节点和类的定义2.二叉搜索树的构造函数3.二叉搜索树的拷贝构造4.二叉树搜索树的赋值重载5.二叉搜索树的析构函数6.二叉搜索树的中序遍历7.二叉搜索树的查找8.二叉搜索树的插入9.二叉搜索树的删除…

瑞吉外卖 - 分页查询分类功能(12)

某马瑞吉外卖单体架构项目完整开发文档&#xff0c;基于 Spring Boot 2.7.11 JDK 11。预计 5 月 20 日前更新完成&#xff0c;有需要的胖友记得一键三连&#xff0c;关注主页 “瑞吉外卖” 专栏获取最新文章。 相关资料&#xff1a;https://pan.baidu.com/s/1rO1Vytcp67mcw-PD…

【Android 面经分享】阿里技术专家的 5年 Android 开发的求职之路

作者:yechaoa 来源:https://juejin.cn/post/6996551155220217869 前言 前段时间在看机会&#xff0c;本文就是我对求职过程的一个总结。 同时&#xff0c;也作为一个面试官&#xff0c;来说说求职中需要注意的点。 各大厂的面试会考核哪些知识点5年开发应该具备哪些技术要点…

chatgpt赋能Python-pycharm取消venv

PyCharm取消venv&#xff1a;一种更简便的虚拟环境管理方式 虚拟环境是Python开发中的重要组成部分之一。它可以让您在同一台机器上使用不同的Python版本、不同的库以及不同的项目而不会干扰彼此之间的功能独立性。而在Python开发中&#xff0c;venv是创建虚拟环境的常用方式之…

chatgpt赋能Python-pycharm怎么关联

Pycharm怎么关联——提高Python开发效率的关键步骤 作为一名有10年Python编程经验的工程师&#xff0c;我深知在日常开发中如何提高Python的编程效率至关重要。而Pycharm则是Python领域最常用的IDE之一&#xff0c;其强大的代码编辑和调试功能&#xff0c;深受开发者的喜爱。 …

Linux驱动开发 --- CCF时钟框架

0. CCF时钟框架概览 linux内核的CCF时钟框架可以分为三层&#xff0c;每一层的职责以及彼此的关系如下图所示 对CCF框架的分析也将以如下几个方向入手&#xff1a; consumer&#xff08;也就是device driver&#xff09;如何使用CCFprovider如何借助CCF管理系统的时钟资源CC…

前端BFC

一、首先我们要先了解常见的定位方案&#xff0c;总共3种&#xff08;普通流、浮动、绝对定位&#xff09; 而BFC是属于普通流的 我们可以把BFC看作为页面的一块渲染区域&#xff0c;他有着自己的渲染规则 简单来说BFC可以看作元素的一种属性&#xff0c;当元素拥有了BFC属性…

ChatGPT:2. 使用OpenAI创建自己的AI网站:1. 初探API

使用OpenAI创建自己的AI网站 如果你还是一个OpenAI的小白&#xff0c;有OpenAI的账号&#xff0c;但想调用OpenAI的API搞一些有意思的事&#xff0c;那么这一系列的教程将仔细的为你讲解如何使用OpenAI的API制作属于自己的AI网站。博主只能利用下班时间更新&#xff0c;进度慢…

自学spring个人笔记

目录 如何学习spring&#xff1f; 如何查看自己电脑是否安装了spring boot Spring Boot CLI安装成功 springboot的版本2.7.12(SNAPSHOT)与2.7.11有什么区别&#xff1f; 报错解决 Plugin org.springframework.boot:spring-boot-maven-plugin:not found 在maven pom.xml中…

【AFNetWorking源码(二)AFURLSessionManger和AFHTTPSessionManager】

前言 学习了Mananger的初始化和以GET请求为例的过程&#xff0c;发现整个过程离不开AFHTTPSessionManager和AFURLSessionManger的某些方法。这两个是AFN的重要的网络通信模块内容&#xff0c;对它们作揖详细的学习。 AFURLSessionManager和AFHTTPSessionManager都是AFNetwork…

chatgpt赋能Python-mac电脑安装python

在Mac电脑上轻松安装Python Python是一种高级编程语言&#xff0c;常用于数据科学、机器学习和Web开发等领域。如果你是一名Mac电脑用户&#xff0c;那么安装Python将会让你受益匪浅。本文将提供详细的操作步骤&#xff0c;让你轻松安装Python并开始学习编程。 第一步&#x…

【Linux】进程地址空间(带你认清内存的本质)

&#x1f525;&#x1f525; 欢迎来到小林的博客&#xff01;&#xff01;       &#x1f6f0;️博客主页&#xff1a;✈️小林爱敲代码       &#x1f6f0;️博客专栏&#xff1a;✈️Linux之路       &#x1f6f0;️社区 :✈️ 进步学堂       &a…

Linux:chmod chown 权限管理

基础权限有以下三个 r 读 4 w 写 2 x 执行 1 - 无此权限 0 开头的第一个字母是这个的类型 d 目录 - 普通文件 l 链接文件 常见的三种 只不过今天不讲这个 从第二个字母开始看起 三个字母为一组 一共…

【EfficientDet】《EfficientDet:Scalable and Efficient Object Detection》

CVPR-2020 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method4.1 BiFPN4.2 EfficientDet 5 Experiments5.1 Datasets5.2 EfficientDet for Object Detection5.3 EfficientDet for Semantic Segmentation5.4 Ablation Study 6 Conclusio…