【数据结构趣味多】顺序表基本操作实现(Java)

简介: 【数据结构趣味多】顺序表基本操作实现(Java)

顺序表

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



1.定义顺序顺序表

public class SeqList {
    public int[] elem;
    public int usedSize;//目前存储元素个数
    //默认容量
    private static final int DEFAULT_SIZE = 10;
    public SeqList() {
        this.elem = new int[DEFAULT_SIZE];
    }
}

   上方定义类SeqList即是顺序表,定义elem数组存储数据,定义usedSize表示当前数组中包含多少个元素,定义DEFAULT_SIZE值为了在构造方法中将顺序表初始化为DEFAULT_SIZE大小的数组。


2.顺序表功能

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

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

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

   public boolean contains(int toValue) { return true; }    // 判定是否包含某个元素

   public int indexOf(int toValue) { return -1; }    // 查找某个元素对应的位置

   public int get(int pos) { return -1; }    // 获取 pos 位置的元素

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

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

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

   public void clear() { }    // 清空顺序表

上面是顺序表当中常用的函数。


3.函数实现(java实现)?

打印顺序表display()函数

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

代码解读:

       打印函数顾名思义就是将顺序表中所有的数据打印出来。打印完的标准就是将顺序表中的数组完全输出,因此用usedSize作为终止条件,

新增元素函数add() (默认在数组最后新增)

public void add(int data) {
        if (this.usedSize == elem.length) {
            this.elem = Arrays.copyOf(elem, elem.length * 2;
        }
        elem[usedSize] = data;
        usedSize++;
    }/

代码解读:

       此函数是增加顺序表中元素的函数。增加元素时,有一点需要注意,你的顺序表是否含有空间放入新的元素。使用函数isFull()判断,若没有满就正常增加,若已满,先对顺序表扩容,再进行增加。

       如何判断顺序表满没满?当数组的长度等于数组中包含元素就为满。

       当数据载入顺序表成功后,数组中包含元素个数usedSize就需要加1。

在 pos 位置新增元素add()函数(与上方函数构成重载)

public void add(int pos, int data) {
        if (pos < 0 || pos > usedSize) {
            throw new ArrayIndexException("下标非法,请检查");
        }
        if (this.usedSize == elem.length) {
            this.elem = Arrays.copyOf(elem, elem.length * 2;
        }
        for (int i = usedSize - 1; i >= pos; i--) {
            elem[i + 1] = elem[i];
        }
        elem[pos] = data;
        usedSize++;
    }

代码解读:

       我们要判断传过来的下标的合法性;分析pos的取值范围:我们要把新增函数放到现在已有元素之间,因此我们可以知道,pos的范围应该是 0<=pos<usedSize.若给定的下标不合法,我们就抛出一个异常,让程序停下来。

       再者这个函数功能也是添加,因此我们也需要判断顺序表空间的问题。

       若我们插入的位置已有元素,我们需把从pos位置的元素向后移,为data数据挪开位置。

       当数据载入顺序表成功后,数组中包含元素个数usedSize就需要加1。

判定是否包含某个元素contains()函数

public boolean contains(int toValue) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toValue) {
                return true;
            }
        }
        return false;
    }

代码解读:

       拿到需要找的数据toValue,遍历数组,将数组中的所有值与toValue进行比较,若数组中的值有与toValue相等,那么就返回true,否则返回false。

查找某个元素对应位置indexOf() 函数

public int indexOf(int toValue) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toValue) {
                return i;
            }
        }
        return -1;
    }

代码解读:

        同上方思想一致,拿到需要找的数据toValue,遍历数组,将数组中的所有值与toValue进行比较,若数组中的值有与toValue相等,那么就返回下标i,否则返回-1。

获取pos位置的元素get()函数

public int get(int pos) {
        if(pos<0||pos>=usedSize){
            throw new ArrayIndexException("下标非法,请查看!");
        }
        return elem[pos];
    }

代码解读:

       我们要判断下标是否合法,我们需要顺序表中的元素,因此pos不能超过顺序表中第一个元素的下标和最后一个元素的下标,即下标是0<=pos<usedSize,如果不在这个范围内,我们抛出一个异常,让程序停下来。

将pos位置的元素更新为value set()函数

public void set(int pos, int value) {
        if(pos<0||pos>=usedSize){
            throw new ArrayIndexException("下标错误,请查看!");
        }
        elem[pos] = value;
    }

代码解读:

       同上方一样,我们要判断下标是否合法,我们需要顺序表中的元素,因此pos不能超过顺序表中第一个元素的下标和最后一个元素的下标,即下标是0<=pos<usedSize,如果不在这个范围内,我们抛出一个异常,让程序停下来。

       最后将value赋到pos位置

删除第一个关键字key remove()函数

public boolean remove(int key) {
        int index = indexOf(key);
        if (index == -1) {
            System.out.println("没有这个数据");
            return false;
        }
        for (int i = index; i < usedSize - 1; i++) {
            elem[i] = elem[i + 1];
        }
        usedSize--;
        elem[usedSize] = 0;
        return true;
    }

代码解读:

       我们先调用indexOf()函数,判断顺序表中是否有我们删除的值,若有找到这个值的下标,没有就返回false。有就以覆盖的方式,将index下标的元素用他后一个元素覆盖,一直往复到最后一个元素,因为删除了一个元素,因此将使用大小usedSize减一,因为在覆盖时,最后一个后面没有元素了,因此没有覆盖,我们将他置为0。

获得顺序表的长度size()函数

public int size() {
        return usedSize;
    }

代码解读:

       当前数组中包含多少个元素,顺序表就是多长,因此顺序表的长度就是usedSize的大小。

清空顺序表clear()函数

public void clear() {
        usedSize = 0;
    }

代码解读:

       因为所有的函数都是围绕这usedSisz进行构造的,我们只需将usedSize置为0,其他函数就无法进行运行(此处并非范例)

其中异常的定义:

package SeqList;
public class ArrayIndexException extends RuntimeException{
        public ArrayIndexException() {
        }
        public ArrayIndexException(String message) {
            super(message);
        }
}


4.程序实例运行

package SeqList;
import java.awt.*;
public class test {
    public static void main(String[] args) {
        SeqList seqList =new SeqList();
        //添加数据
        seqList.add(1);
        seqList.add(2);
        seqList.add(3);
        seqList.add(4);
        seqList.add(5);
        //打印
        System.out.print("当前数组元素:");
        seqList.display();
        //值所在的下标
        System.out.print("值所在的下标:");
        System.out.println(seqList.indexOf(3));
        //是否包含这个值
        System.out.print("是否包含这个值:");
        System.out.println(seqList.contains(2));
        //获得下标所在位置元素
        System.out.print("获得下标所在位置元素:");
        System.out.println(seqList.get(3));
        //修改下标的值
        System.out.print("修改下标的值:");
        seqList.set(3,12);
        seqList.display();
        //删除关键字key
        System.out.print("删除关键字key:");
        seqList.remove(2);
        seqList.display();
        //获得长度
        System.out.print("获得当前顺序表长度:");
        System.out.println(seqList.size());
    }
}

上方实例运行结果如下:



小节

顺序表也是分情况使用的,如何判断呢?总结了它的优缺点,可以作为参考。


 优点:

无需为表示表中元素之间的逻辑关系而增加额外的存储空间。

可以快速地获取表中任意位置的元素。


       缺点:

插入和删除操作需要移动大量元素(时间复杂度高)。

当线性表长度变化较大时,难以确定存储空间的容量。

造成存储空间的“碎片”。(当我们添加元素时,例如我们有101个元素,数组初始大小为100,扩容为1.5倍,初始大小无法存储全部元素,因此需要扩容,扩容为150大小,这就浪费了49个空间)


相关文章
|
2月前
|
存储 人工智能 算法
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
这篇文章详细介绍了Dijkstra和Floyd算法,这两种算法分别用于解决单源和多源最短路径问题,并且提供了Java语言的实现代码。
84 3
数据结构与算法细节篇之最短路径问题:Dijkstra和Floyd算法详细描述,java语言实现。
|
2月前
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
46 1
|
2月前
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
89 2
|
2月前
|
存储 Java 开发者
Java Map实战:用HashMap和TreeMap轻松解决复杂数据结构问题!
【10月更文挑战第17天】本文深入探讨了Java中HashMap和TreeMap两种Map类型的特性和应用场景。HashMap基于哈希表实现,支持高效的数据操作且允许键值为null;TreeMap基于红黑树实现,支持自然排序或自定义排序,确保元素有序。文章通过具体示例展示了两者的实战应用,帮助开发者根据实际需求选择合适的数据结构,提高开发效率。
64 2
|
21天前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
40 6
|
27天前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
1月前
|
存储 算法 安全
2024重生之回溯数据结构与算法系列学习之顺序表【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找等具体详解步骤以及举例说明
|
1月前
|
存储 C语言
【数据结构】顺序表(c语言实现)(附源码)
本文介绍了线性表和顺序表的基本概念及其实现。线性表是一种有限序列,常见的线性表有顺序表、链表、栈、队列等。顺序表是一种基于连续内存地址存储数据的数据结构,其底层逻辑是数组。文章详细讲解了静态顺序表和动态顺序表的区别,并重点介绍了动态顺序表的实现,包括初始化、销毁、打印、增删查改等操作。最后,文章总结了顺序表的时间复杂度和局限性,并预告了后续关于链表的内容。
61 3
|
1月前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之顺序表习题精讲【无论是王道考研人还真爱粉都能包会的;不然别给我家鸽鸽丢脸好嘛?】
顺序表的定义和基本操作之插入;删除;按值查找;按位查找习题精讲等具体详解步骤以及举例说明
|
2月前
|
存储 算法 Java
Java 中常用的数据结构
【10月更文挑战第20天】这些数据结构在 Java 编程中都有着广泛的应用,掌握它们的特点和用法对于提高编程能力和解决实际问题非常重要。
30 6