【数据结构趣味多】顺序表基本操作实现(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个空间)


相关文章
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
742 1
|
存储 Java
告别混乱!用Java Map优雅管理你的数据结构
【10月更文挑战第17天】在软件开发中,随着项目复杂度增加,数据结构的组织和管理至关重要。Java中的Map接口提供了一种优雅的解决方案,帮助我们高效、清晰地管理数据。本文通过在线购物平台的案例,展示了Map在商品管理、用户管理和订单管理中的具体应用,有效提升了代码质量和维护性。
364 2
|
存储 Java
Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。
【10月更文挑战第19天】本文详细介绍了Java中的HashMap和TreeMap,通过具体示例展示了它们在处理复杂数据结构问题时的应用。HashMap以其高效的插入、查找和删除操作著称,而TreeMap则擅长于保持元素的自然排序或自定义排序,两者各具优势,适用于不同的开发场景。
252 1
|
存储 安全 Java
Java 集合面试题从数据结构到 HashMap 源码剖析详解及长尾考点梳理
本文深入解析Java集合框架,涵盖基础概念、常见集合类型及HashMap的底层数据结构与源码实现。从Collection、Map到Iterator接口,逐一剖析其特性与应用场景。重点解读HashMap在JDK1.7与1.8中的数据结构演变,包括数组+链表+红黑树优化,以及put方法和扩容机制的实现细节。结合订单管理与用户权限管理等实际案例,展示集合框架的应用价值,助你全面掌握相关知识,轻松应对面试与开发需求。
655 3
|
存储 Java 编译器
Java 中 .length 的使用方法:深入理解 Java 数据结构中的长度获取机制
本文深入解析了 Java 中 `.length` 的使用方法及其在不同数据结构中的应用。对于数组,通过 `.length` 属性获取元素数量;字符串则使用 `.length()` 方法计算字符数;集合类如 `ArrayList` 采用 `.size()` 方法统计元素个数。此外,基本数据类型和包装类不支持长度属性。掌握这些区别,有助于开发者避免常见错误,提升代码质量。
1193 1
|
机器学习/深度学习 存储 C++
【C++数据结构——线性表】顺序表的基本运算(头歌实践教学平台习题)【合集】
本文档介绍了线性表的基本运算任务,涵盖顺序表和链表的初始化、销毁、判定是否为空、求长度、输出、查找元素、插入和删除元素等内容。通过C++代码示例详细展示了每一步骤的具体实现方法,并提供了测试说明和通关代码。 主要内容包括: - **任务描述**:实现顺序表的基本运算。 - **相关知识**:介绍线性表的基本概念及操作,如初始化、销毁、判定是否为空表等。 - **具体操作**:详述顺序表和链表的初始化、求长度、输出、查找、插入和删除元素的方法,并附有代码示例。 - **测试说明**:提供测试输入和预期输出,确保代码正确性。 - **通关代码**:给出完整的C++代码实现,帮助完成任务。 文档
578 5
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
363 5
|
数据库
数据结构中二叉树,哈希表,顺序表,链表的比较补充
二叉搜索树,哈希表,顺序表,链表的特点的比较
数据结构中二叉树,哈希表,顺序表,链表的比较补充
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
534 6