数据结构 —— Java自定义代码实现顺序表,包含测试用例以及ArrayList的使用以及相关算法题

简介: 文章详细介绍了如何用Java自定义实现一个顺序表类,包括插入、删除、获取数据元素、求数据个数等功能,并对顺序表进行了测试,最后还提及了Java中自带的顺序表实现类ArrayList。

顺序表简介

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

自定义顺序表

    以下是顺序表的类以及相关方法,接下来我将带着你**手把手**地将里面的方法**补充完**并**讲解代码逻辑**,只想看完整源码的下拉到最下面或点击目录中的完整源码,即可直接到对应位置

    首先,此处顺序表我们选择底层是由数组来实现,并定义一个变量存放数组有效元素个数,一个常量用来初始化数组的内存空间
public class SeqList {
    private int[] array;
    private int size;
    // 默认构造方法
    SeqList(){ }
    // 判断是否满了,如果满了,自动扩容
    public void fullResize(){   }
    // 新增元素,默认在数组最后新增
    public void add(int data) { }
    // 在 pos 位置新增元素
    public void add(int pos, int data) { }
    // 判定是否包含某个元素
    public boolean contains(int toFind) { return true; }
    // 查找某个元素对应的位置
    public int indexOf(int toFind) { return -1; }
    // 获取 pos 位置的元素
    public int get(int pos) { return -1; }
    // 给 pos 位置的元素设为 value
    public void set(int pos, int value) { }
    //删除第一次出现的关键字key
    public void remove(int toRemove) { }
    // 获取顺序表长度
    public int size() { return 0; }
    // 清空顺序表
    public void clear() { }
    // 打印顺序表,注意:该方法并不是顺序表中的方法,为了方便看测试结果给出的
    public void display() { }
}

SeqList —— 构造方法

定义构造方法,初始化数组长度/空间,长度为上面定义的常量

    // 构造方法,初始化5个空间
    public SeqList(){
        this.elem = new int[DEFAULT_CAPACITY];
    }

display —— 打印顺序表

遍历顺序表,打印每个有效元素

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

fullResize —— 判断是否满了,满了则扩容

判断是否满了,如果满了,自动扩容

    // 判断是否满了,如果满了,自动扩容
    public void fullResize(){
        if(this.elem.length == count){
            elem = Arrays.copyOf(elem, 2*elem.length);
        }
    }

add —— 新增元素,默认在数据最后

    新增元素,**默认在数据最后**,add执行开始,先调用fullResize判断顺序表是否满了,满了则先扩容,再添加元素,因为满了的情况下,没有位置可添加元素
    // 新增元素,默认在数据最后
    public void add(int data){
        fullResize();
        elem[count] = data;
        count++;
    }

add —— 在任意位置新增元素

    **在pos位置新增元素**,先判断pos是否合法,比如插入下标位置为-1或超出数组有效元素个数范围,那肯定不合法,不合法即抛出异常,这里的异常是**我们自己定义的**,目录中点击 **自定义异常类** 即可跳转,也可手动往下翻看

如果合法则挪动数据并插入

为什么有两个add?

这里属于方法的重载,会根据传递的参数自动选择对应的add方法

    // 在 pos 位置新增元素
    public void add(int pos, int data){
        fullResize();
        if(pos < 0 || pos > this.count){
            throw new PosOutBoundsException("add 数据时,位置不合法!");
        }
        // 挪动数据
        for(int i = this.count; i > pos; i--){
            this.elem[i] = this.elem[i-1];
        }
        // 存数据
        this.elem[pos] = data;
        this.count++;
    }

contains —— 判断是否包含某个元素

遍历顺序表,依次比较

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

indexOf —— 查找某个元素对应的位置下标

    // 查找某个元素对应的位置下标
    public int indexOf(int toFind){
        for (int i = 0; i < this.count; i++) {
            if(toFind == this.elem[i]){
                return i;
            }
        }
        return -1;  // 表示没有该元素
    }

checkPos —— 判断参数是否合法

此处的是否合法范围的右边界是按有效元素个数来计算的

    // 判断参数是否合法(按有效元素算)
    public boolean checkPos(int pos){
        if(pos < 0 || pos >= this.count){
            return false;
        }
        return true;
    }

get —— 获取 pos 位置的元素

如果pos不合法,则抛出异常

    // 获取pos位置的元素
    public int get(int pos){
        if(!checkPos(pos)){
            throw new PosOutBoundsException("get 数据时,位置不合法!");
        }
        return this.elem[pos];
    }

set —— 修改/更新元素

给pos位置的元素设置为value [修改/更新]

    // 给pos位置的元素设置为value [修改、更新]
    public void set(int pos, int value){
        if(!checkPos(pos)){
            throw new PosOutBoundsException("set 数据时,位置不合法! ");
        }
        this.elem[pos] = value;
    }

size —— 获取顺序表的长度

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

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

    // 删除第一次出现的关键字key
    public void remove(int toRemove){
        // 如果列表为空,直接返回
        if(this.count == 0){
            return;
        }
        int index = indexOf(toRemove);
        if(index == -1){
            return;  //没有要删除的关键字
        }
        for(int i = index; i < this.count-1; i++){
            this.elem[i] = this.elem[i+1];
        }
        this.count--;
    }

clear —— 清空顺序表

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

自定义顺序表全部代码

下面的代码在上面都有,只是下面将其完整的展示了出来,供您更有效地复制和阅读代码

友情提示:下面中的 PosOutBoundsException 是我们自定义的异常,目录中点击 自定义异常类 即可跳转,也可手动往下翻看

import java.util.Arrays;

// 顺序表
public class SeqList {
    private int[] elem;
    private int count;   // 计算当前存储有效元素个数

    private static final int DEFAULT_CAPACITY = 5;  // 初始化内存空间

    // 构造方法,初始化5个空间
    public SeqList(){
        this.elem = new int[DEFAULT_CAPACITY];
    }

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

    // 判断是否满了,如果满了,自动扩容
    public void fullResize(){
        if(this.elem.length == count){
            elem = Arrays.copyOf(elem, 2*elem.length);
        }
    }
    // 新增元素,默认在数据最后
    public void add(int data){
        fullResize();
        elem[count] = data;
        count++;
    }


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

    // 查找某个元素对应的位置下标
    public int indexOf(int toFind){
        for (int i = 0; i < this.count; i++) {
            if(toFind == this.elem[i]){
                return i;
            }
        }
        return -1;  // 表示没有该元素
    }

    // 判断参数是否合法(按有效元素算)
    public boolean checkPos(int pos){
        if(pos < 0 || pos >= this.count){
            return false;
        }
        return true;
    }

    // 获取pos位置的元素
    public int get(int pos){
        if(!checkPos(pos)){
            throw new PosOutBoundsException("get 数据时,位置不合法!");
        }
        return this.elem[pos];
    }

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

    // 给pos位置的元素设置为value [修改、更新]
    public void set(int pos, int value){
        if(!checkPos(pos)){
            throw new PosOutBoundsException("set 数据时,位置不合法! ");
        }
        this.elem[pos] = value;
    }

    // 在 pos 位置新增元素
    public void add(int pos, int data){
        fullResize();
        if(pos < 0 || pos > this.count){
            throw new PosOutBoundsException("add 数据时,位置不合法!");
        }
        // 挪动数据
        for(int i = this.count; i > pos; i--){
            this.elem[i] = this.elem[i-1];
        }
        // 存数据
        this.elem[pos] = data;
        this.count++;
    }

    // 删除第一次出现的关键字key
    public void remove(int toRemove){
        // 如果列表为空,直接返回
        if(this.count == 0){
            return;
        }
        int index = indexOf(toRemove);
        if(index == -1){
            return;  //没有要删除的关键字
        }
        for(int i = index; i < this.count-1; i++){
            this.elem[i] = this.elem[i+1];
        }
        this.count--;
    }


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

自定义异常类

单独定义一个.Java文件存写该代码

    用来在下标不合法等情况下抛出异常,第二个构造方法的意思是抛出异常时会打印出message中的信息
// 自定义异常类
public class PosOutBoundsException extends RuntimeException{
    public PosOutBoundsException(){

    }

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

自定义顺序表的测试用例

    此段代码用来验证我们写的自定义顺序表是否正确以及功能完整程度,从测试可以看出我们写的代码非常Good
public class Main {
    public static void main(String[] args) {
//        SeqList seqList = new SeqList();
//        for(int i = 0; i < 10; i++){
//            seqList.add(i,i*10);
//        }
//        seqList.display();

        SeqList list = new SeqList();

        // 添加元素并打印列表
        list.add(1);
        list.add(2);
        list.add(3);
        list.display(); // 应该打印 "1 2 3 "

        // 判断是否包含某个元素
        System.out.println(list.contains(2)); // 应该打印 true
        System.out.println(list.contains(4)); // 应该打印 false

        // 查找元素的位置下标
        System.out.println(list.indexOf(3)); // 应该打印 2
        System.out.println(list.indexOf(4)); // 应该打印 -1

        // 获取元素
        System.out.println(list.get(0)); // 应该打印 1
        System.out.println(list.get(2)); // 应该打印 3

        // 获取列表长度
        System.out.println(list.size()); // 应该打印 3

        // 设置元素
        list.set(1, 5);
        list.display(); // 应该打印 "1 5 3 "

        // 在指定位置插入元素
        list.add(1, 4);
        list.display(); // 应该打印 "1 4 5 3 "

        // 删除第一次出现的元素
        list.remove(4);
        list.display(); // 应该打印 "1 5 3 "

        // 清空列表
        list.clear();
        list.display(); // 应该打印空行
        System.out.println(list.size()); // 应该打印 0
    }
}

控制台输出结果如下:(完全正确)

Java中自带的顺序表 —— ArrayList

📜ArrayList简介及使用全方位手把手教学(带源码),用ArrayList实现洗牌算法,3个人轮流拿牌(带全部源码)

🧸至此,感谢您阅读这篇博客,祝您生活愉快! o (ˉ▽ˉ;)

目录
相关文章
|
3月前
|
Java 开发工具
【Azure Storage Account】Java Code访问Storage Account File Share的上传和下载代码示例
本文介绍如何使用Java通过azure-storage-file-share SDK实现Azure文件共享的上传下载。包含依赖引入、客户端创建及完整示例代码,助你快速集成Azure File Share功能。
405 5
|
3月前
|
Java 数据处理 API
为什么你的Java代码应该多用Stream?从循环到声明式的思维转变
为什么你的Java代码应该多用Stream?从循环到声明式的思维转变
292 115
|
3月前
|
安全 Java 编译器
为什么你的Java代码需要泛型?类型安全的艺术
为什么你的Java代码需要泛型?类型安全的艺术
207 98
|
3月前
|
安全 Java 容器
告别繁琐判空:Optional让你的Java代码更优雅
告别繁琐判空:Optional让你的Java代码更优雅
|
3月前
|
安全 Java 容器
告别空指针噩梦:Optional让Java代码更优雅
告别空指针噩梦:Optional让Java代码更优雅
419 94
|
3月前
|
Java 编译器 API
java最新版和java8的区别,用代码展示
java最新版和java8的区别,用代码展示
351 43
|
3月前
|
安全 Java 测试技术
《深入理解Spring》单元测试——高质量代码的守护神
Spring测试框架提供全面的单元与集成测试支持,通过`@SpringBootTest`、`@WebMvcTest`等注解实现分层测试,结合Mockito、Testcontainers和Jacoco,保障代码质量,提升开发效率与系统稳定性。
|
3月前
|
存储 Java 索引
用Java语言实现一个自定义的ArrayList类
自定义MyArrayList类模拟Java ArrayList核心功能,支持泛型、动态扩容(1.5倍)、增删改查及越界检查,底层用Object数组实现,适合学习动态数组原理。
165 4
|
3月前
|
机器学习/深度学习 算法 机器人
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
【水下图像增强融合算法】基于融合的水下图像与视频增强研究(Matlab代码实现)
401 0
|
3月前
|
数据采集 分布式计算 并行计算
mRMR算法实现特征选择-MATLAB
mRMR算法实现特征选择-MATLAB
272 2