Java数据结构之顺序表篇

 更新时间:2022年01月19日 16:51:36   作者:ViolentAsteroid  
顺序表,全名顺序存储结构,是线性表的一种。线性表用于存储逻辑关系为“一对一”的数据,顺序表自然也不例外,不仅如此,顺序表对数据物理存储结构也有要求。顺序表存储数据时,会提前申请一整块足够大小的物理空间,然后将数据依次存储起来,存储时数据元素间不留缝隙

一.线性表 

线性表( linear list ) 是 n 个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见 的线性表:顺序表、链表、栈、队列、字符串... 线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储 时,通常以数组和链式结构的形式存储。

二.顺序表

1.概念及结构

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

而顺序表一般可以分为两类:静态顺序表、动态顺序表

2.顺序表的实现

首先我们将顺序表的成员属性以及构造函数写好,接下来实现具体接口

public class MyArrayList {
 
    public int[] elem;
    public int usedSize;//有效的数据个数,默认值为0
 
    public MyArrayList() {//初始化一个数组,容量为5
        this.elem = new int[5];
    }
 
}

打印顺序表

只需要遍历完数组,然后将其打印出来即可

具体的代码实现:

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

获取顺序表的有效长度

有效长度就是已经用过的元素,返回usedSize即可 

具体的代码实现:

// 获取顺序表的有效数据长度
    public int size() {
            return usedSize;
    }

在pos位置新增元素

具体的操作分为四步:

1、判断pos位置是否合法,即pos既不能小于0,也不能大于有效数据个数

2、判断顺序表是否已满,如果满了,需要Arrays.CopyOf()进行扩容

3、将pos后的元素依次后移,即 elem[i+1]=elem[i]

4、将目标元素data放入pos下标对应位置,即elem[pos]=data

具体的代码实现:

// 在 pos 位置新增元素
    public void add(int pos, int data) {
        //1.判断pos位置是否合法
        if (pos<0 || pos>usedSize){
            System.out.println("pos位置不合法");
            return;
        }
        //2.判断usedSize是否已满
        if (isFull()){
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        //3.开始挪数据,并且给pos位置赋值
        for (int i = usedSize-1; i >= pos ; i--) {
                elem[i+1]=elem[i];//把i下标的值给i+1
            }
        this.elem[pos]=data;
        this.usedSize++;//说明存放成功
    }
    public boolean isFull(){
            return this.usedSize == this.elem.length;
    }

判断是否包含某个元素

只需要传入需要查找的元素toFind,然后遍历查找即可

具体的代码实现:

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

查找某个元素对应的位置

跟上一个操作一样,使用遍历查找到元素后,返回其下标即可

具体的代码实现:

// 查找某个元素对应的位置
    public int search(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i]==toFind)
                return i;//找到了返回i下标
        }
        return -1; //找不到返回-1,因为数组没有负数下标
    }

获取/查找pos位置的元素

凡是传入pos位置,我们都需要判断pos是否合法,也要查看顺序表是否为空,如果合法且不为空直接返回该下标对应的元素即可

具体的代码实现:

// 获取 pos 位置的元素
    public int getPos(int pos) {
        if (pos<0 || pos>this.usedSize){
            System.out.println("pos位置不合法");
            return -1;//说明pos位置不合法
        }
        if(isEmpty()){
            System.out.println("顺序表为空");
            return -1;
        }
        return this.elem[pos];//返回pos位置的值
    }
    public boolean isEmpty(){
        return this.usedSize==0;
    }

给pos位置的元素设为value

依然先判断pos位置是否合法,再判断顺序表是否为空,如果合法且不为空,则将value赋值给pos下标对应的元素

具体的代码实现:

// 给 pos 位置的元素设为/更新为 value
    public void setPos(int pos, int value) {
        //还是要先判断pos位置的合法性
        if (pos<0 || pos>usedSize){
            System.out.println("pos位置不合法");
            return;
        }
        if(isEmpty()){
            System.out.println("顺序表为空");
            return ;
        }
        this.elem[pos] = value;//将pos位置的元素更新为value
    }

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

具体步骤如下:

1、判断顺序表是否为空(除了增加元素是判断顺序表是否已满,其他的都是判断是否为空)

2、调用我们上边写的search函数,看是否存在该元素

3、如果存在,则从该元素起,将后面的元素往前挪,将要删除的元素覆盖

具体的代码实现如下:

//删除第一次出现的关键字key
    public void remove(int toRemove) {
        if (isEmpty()){
            System.out.println("顺序表为空");
            return;
        }
        int index = search(toRemove);
        if (index==-1) {
            System.out.println("没有你要删除的数字");
            return;
        }
        for (int i = index; i < usedSize-1; i++) {
            this.elem[i]=this.elem[i+1];
        }
        this.usedSize--;
        //this.elem[usedSize]=null; 如果数组当中是引用类型,则要将其置为空
    }

清空顺序表

清空顺序表,只需要把有效长度置于0即可

具体的代码实现:

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

3.顺序表的优、缺点

优点:由于顺序表是物理和逻辑上都连续的,可以快速查找到当前数据,时间复杂度为O(1)

缺点:

1、删除和插入数据的时候,都需要移动数据,时间复杂度为O(N)

2、扩容也是问题,增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到200,我们再继续插入5个数据,无后续数据插入,那么就浪费了95个数据空间

那么顺序表的缺点怎么才能解决呢?链表很好的解决了顺序表的缺点,随用随取,需要空间的时候就new一个结点。需要注意的是,链表是物理上不连续,而逻辑上连续。

三.顺序表的实现代码汇总

 
public class MyArrayList {
 
    public int[] elem;
    public int usedSize;
    public MyArrayList() {
        this.elem = new int[5];
    }
 
 
    // 打印顺序表
    public void display() {
        for (int i = 0; i <this.usedSize ; i++) {
            System.out.print(elem[i]+" ");
        }
        System.out.println();
    }
 
    // 获取顺序表的有效数据长度
    public int size() {
            return usedSize;
    }
 
    // 在 pos 位置新增元素
    public void add(int pos, int data) {
        //1.判断pos位置是否合法
        if (pos<0 || pos>usedSize){
            System.out.println("pos位置不合法");
            return;
        }
        //2.判断usedSize是否已满
        if (isFull()){
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);
        }
        //3.开始挪数据,并且给pos位置赋值
        for (int i = usedSize-1; i >= pos ; i--) {
                elem[i+1]=elem[i];//把i下标的值给i+1
            }
        this.elem[pos]=data;
        this.usedSize++;//说明存放成功
    }
    public boolean isFull(){
            return this.usedSize == this.elem.length;
    }
 
 
    // 判定是否包含某个元素
    public boolean contains(int toFind) {
        for (int i = 0; i <this.usedSize ; i++) {
            if (this.elem[i]==toFind)
                return true;
        }
        return false;
    }
 
 
    // 查找某个元素对应的位置
    public int search(int toFind) {
        for (int i = 0; i < this.usedSize; i++) {
            if (this.elem[i]==toFind)
                return i;//找到了返回i下标
        }
        return -1; //找不到返回-1,因为数组没有负数下标
    }
 
 
    // 获取 pos 位置的元素
    public int getPos(int pos) {
        if (pos<0 || pos>this.usedSize){
            System.out.println("pos位置不合法");
            return -1;//说明pos位置不合法
        }
        if(isEmpty()){
            System.out.println("顺序表为空");
            return -1;
        }
        return this.elem[pos];//返回pos位置的值
    }
    public boolean isEmpty(){
        return this.usedSize==0;
    }
 
    // 给 pos 位置的元素设为/更新为 value
    public void setPos(int pos, int value) {
        //还是要先判断pos位置的合法性
        if (pos<0 || pos>usedSize){
            System.out.println("pos位置不合法");
            return;
        }
        if(isEmpty()){
            System.out.println("顺序表为空");
            return ;
        }
        this.elem[pos] = value;//将pos位置的元素更新为value
    }
 
    //删除第一次出现的关键字key
    public void remove(int toRemove) {
        if (isEmpty()){
            System.out.println("顺序表为空");
            return;
        }
        int index = search(toRemove);
        if (index==-1) {
            System.out.println("没有你要删除的数字");
            return;
        }
        for (int i = index; i < usedSize-1; i++) {
            this.elem[i]=this.elem[i+1];
        }
        this.usedSize--;
        //this.elem[usedSize]=null; 如果数组当中是引用类型,则要将其置为空
    }
 
    // 清空顺序表
    public void clear() {
        this.usedSize = 0;
 
    }
 
}

到此这篇关于Java数据结构之顺序表篇的文章就介绍到这了,更多相关Java 顺序表内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Java利用布隆过滤器实现快速检查元素是否存在

    Java利用布隆过滤器实现快速检查元素是否存在

    布隆过滤器是一个很长的二进制向量和一系列随机映射函数。布隆过滤器可以用于检索一个元素是否在一个集合中。本文就来详细说说实现的方法,需要的可以参考一下
    2022-10-10
  • Java利用Reflect实现封装Excel导出工具类

    Java利用Reflect实现封装Excel导出工具类

    这篇文章主要为大家详细介绍了Java如何利用Reflect实现封装Excel导出工具类,文中的实现方法讲解详细,具有一定的借鉴价值,需要的可以参考一下
    2022-11-11
  • Java线程状态及切换、关闭线程的正确姿势分享

    Java线程状态及切换、关闭线程的正确姿势分享

    这篇文章主要给大家介绍了关于Java线程状态及切换、关闭线程的正确姿势,文中通过示例代码介绍的非常详细,对大家的学习或者使用Java具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2019-10-10
  • 教你使用Java获取当前时间戳的详细代码

    教你使用Java获取当前时间戳的详细代码

    这篇文章主要介绍了如何使用Java获取当前时间戳,通过两个java示例,向大家展示如何获取java中的当前时间戳,文本通过示例代码给大家展示了java获取当前时间戳的方法,需要的朋友可以参考下
    2022-01-01
  • java计算任意位水仙花数示例(回文数)

    java计算任意位水仙花数示例(回文数)

    这篇文章主要介绍了java计算任意位水仙花数示例(回文数),需要的朋友可以参考下
    2014-05-05
  • JAVA实现JSON后端向前端传递数据

    JAVA实现JSON后端向前端传递数据

    本篇文章主要介绍了JAVA实现JSON后端向前端传递数据,这里整理了详细的代码,具有一定的参考价值,有需要的小伙伴可以参考下。
    2017-03-03
  • Java实现Json字符串与Object对象相互转换的方式总结

    Java实现Json字符串与Object对象相互转换的方式总结

    这篇文章主要介绍了Java实现Json字符串与Object对象相互转换的方式,结合实例形式总结分析了java基于Json-Lib、Org.Json、Jackson、Gson、FastJson五种方式转换json类型相关操作技巧,需要的朋友可以参考下
    2019-03-03
  • java实现写入并保存txt文件的代码详解

    java实现写入并保存txt文件的代码详解

    在本篇文章里小编给大家整理了关于java实现写入并保存txt文件的代码实例内容,需要的朋友们可以参考学习下。
    2020-02-02
  • Java实现的迷宫游戏

    Java实现的迷宫游戏

    这篇文章主要介绍了如何用Java实现一个迷宫游戏,本仓库代码是经过eclipse编译运行过的,一般情况下将本仓库代码下载下来之后,使用eclipse编译直接可以运行。
    2021-04-04
  • spring项目中切面及AOP的使用方法

    spring项目中切面及AOP的使用方法

    我们知道,spring两大核心,IOC(控制反转)和AOP(切面),那为什么要使用AOP,AOP是什么呢?带着这些问题通过本文学习下吧
    2021-06-06

最新评论