顺序表(快速上手数据结构)

在介绍ArrayList之前, 我们需要先了解List.

++List是一个接口++ ,它继承于Collection接口(Collection又继承于最顶层的接口Iterable). 从数据结构的角度来看,List就是一个++线性表(Linear List)++ ,即n个具有相同类型元素的有限序列 , 在该序列上可以执行增删查改等操作.

注意: List是一个接口,不能直接用来实例化. 在集合框架中, ArrayList类和LinkedList类都实现了List接口. 我们可以通过这两个类来实例化对象. 本篇博客主要讲述ArrayList类(顺序表).

目录

顺序表

[1. 新增元素](#1. 新增元素)

[2. 在pos位置新增元素](#2. 在pos位置新增元素)

[3. 判定是否包含某个元素](#3. 判定是否包含某个元素)

[4. 查找某个元素对应的位置,并返回下标](#4. 查找某个元素对应的位置,并返回下标)

[5. 获取pos位置的元素](#5. 获取pos位置的元素)

[6. 给pos位置的元素设为value(给某位置的元素更新)](#6. 给pos位置的元素设为value(给某位置的元素更新))

[7. 删除某数字key](#7. 删除某数字key)

[8. 获取顺序表的长度](#8. 获取顺序表的长度)

9.清空顺序表


顺序表

顺序表中主要有如下几种方法:

java 复制代码
public interface IList {
    void add(int data); //新增元素(默认在数组最后新增)
    
    void add(int pos, int data); //在pos位置新增元素
    
    boolean contains(int toFind); //判定是否包含某个元素
    
    int indexOf(int ToFind); //查找某个元素对应的位置,并返回下标
    
    int get(int pos); //获取pos位置的元素
    
    void set(int pos, int value); //给pos位置的元素设为value(更新)
    
    void remove(int toRemove); //删除第一次出现的关键字key
    
    void size(); //获取顺序表的长度
    
    void clear(); //清空顺序表

    void display(); //打印数组(不属于顺序表中的方法)
}

今天,我们就用Java来实现一遍这七种方法. 相信在我们自己实现完一遍顺序表之后,我们的代码能力和思维会有不小的提升!

首先,我们需要定义一个操作数组,用来让方法对其进行操作:

java 复制代码
public class MyArrayList {
    public int[] elem; //定义一个整型类型的操作数组
    public int usedSize; //定义一个变量表示已使用空间 (没有初始化--默认是0)
    public MyArrayList() { //构造方法 (将数组长度初始化为10)
        this.elem = new int[10];
    }
}

1. 新增元素

void add(int data) 默认在数组的最后新增.

在这里,我们只需要在数组++有数据的位置的后一个++ (即:usedSize位置上 (例如: usedSize=5, 那么0,1,2,3,4 位置上有元素, 将新增数据放到5位置上就行))放上我们要新增的数据 即可.但是:如果数组满了,还能新增吗? -- 不能,此时需要将数组扩容才能继续新增操作.

结合上面两方面的考虑,我们写出如下代码:

java 复制代码
 public void add(int data) {
        if (isFull()) {
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        this.elem[usedSize] = data;
        this.usedSize ++;
    }
    boolean isFull() {
        return (usedSize == elem.length);
    }

我们在main方法里调用它测试一下:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.display();

    }
}

运行结果:

2. 在pos位置新增元素

在pos位置新增元素,我们需要考虑的点有以下几个: (1) 将pos位置后的元素整体向后移. (2) 插入新的数据. (3) 检查pos位置是否合法.

  • 检查pos位置是否合法: pos<0时不合法; pos>usedSize时不合法(pos=usedSize时是合法的,因为此时相当于在数组的最后新增一个元素)
  • 移动元素: 令i等于数组最后一个位置(usedSize-1), 从数组最后一个位置开始遍历数组,将 i位置上的元素赋到 i+1位置上
  • 插入数据: 将数据data放到数组下标为pos的位置上即可. 所有操作完成后, 再让usedSize++即可.

注意: pos位置不合法我们可以写一个异常出来,方便检查和处理.

根据上述步骤,我们可以写出如下代码:

java 复制代码
    public void add(int pos, int data) {
        try{
            checkOfPosAdd(pos); //检查pos是否合法
        }
        catch(PosIllegalException e){
            e.printStackTrace(); //打印异常
        }
        if (isFull()) {
            elem = Arrays.copyOf(elem,2*elem.length); //如果数组满了需要扩容
        }
        for (int i = usedSize-1; i >= pos ; i--) {
            elem[i+1] = elem[i]; //向后移动元素
        }
        elem[pos] = data; //插入新的元素
        usedSize ++;
    }
    private void checkOfPosAdd(int pos) throws PosIllegalException {
        if (pos < 0 || pos > usedSize) {
            throw new PosIllegalException("pos位置不合法");
        }
    }

在main方法中调用:

java 复制代码
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        iList.add(2,88);
        iList.display();

    }
}

运行结果:

3. 判定是否包含某个元素

对于这个方法的实现, 我们只需遍历数组, 看是否有要找的数据,如果有,则返回true

代码:

java 复制代码
    public boolean contains(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toFind) {
                return true;
            }
        }
        return false;
    }

在main方法中调用:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        System.out.println(iList.contains(2));
    }
}

运行结果:

4. 查找某个元素对应的位置,并返回下标

对于这个方法的实现, 我们还是遍历数组. 如果有要找的数据,则返其对应的下标; 如果没有, 则返回-1.

代码:

java 复制代码
    public int indexOf(int toFind) {
        for (int i = 0; i < usedSize; i++) {
            if (elem[i] == toFind) {
                return i;
            }
        }
        return -1;
    }

在main方法中调用:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        System.out.println(iList.indexOf(2));
    }
}

运行结果:

5. 获取pos位置的元素

实现这个方法,分两步: (1) 判断pos位置是否合法. (2) 返回pos位置元素的值.

(1) pos<0 或 pos>=usedSize 时不合法(pos==UsedSize时此位置上没有元素, 所以不合法). 所以这里我们就需要写一个方法来判断pos是否合法.

(2) 返回pos位置的元素: 直接返回即可.

代码:

java 复制代码
public int get(int pos) {
    try{
        checkPosOfGetAndSet(pos);
    }
    catch(PosIllegalException e) {
        e.printStackTrace();
    }
    return elem[pos];

在main方法中调用:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        System.out.println(iList.get(2));
    }
}

运行结果:

6. 给pos位置的元素设为value(给某位置的元素更新)

实现这个方法, 也要分为两步: (1) 判断pos位置是否合法. (2) 给pos位置的元素设为value

代码:

java 复制代码
    public void set(int pos, int value) {
        try{
            checkPosOfGetAndSet(pos);
        }
        catch(PosIllegalException e){
            e.printStackTrace();
        }
        elem[pos] = value;
    }

在main方法中调用:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        iList.set(2,333);
        iList.display();
    }
}

运行结果:

7. 删除某数字key

我们首先要判断这个数字书是否在数组里面.然后在删除(删除的方法是"覆盖"--用后面的数据覆盖前面的数据从而实现对前面数据的删除)

代码:

java 复制代码
    public void remove(int toRemove) {
        int pos = indexOf(toRemove);
        if (pos == -1) {
            System.out.println("没有要删除的数字");
            return; //为什么要写return? 有必要吗?
        }
        for (int i = pos; i < usedSize-1; i++) {
            elem[i] = elem[i+1];
        }
        this.usedSize--;

在main方法中调用:

java 复制代码
public class Test {
    public static void main(String[] args) {
        IList iList = new MyArrayList();//实例化一个MyArraList的对象.
        iList.add(1);
        iList.add(2);
        iList.add(3);
        iList.display();
        iList.remove(2);
        iList.display();
    }
}

运行结果:

8. 获取顺序表的长度

代码:

java 复制代码
    public int size() {
        return this.usedSize;
    }

9.清空顺序表

本例中:数组是基本类型(int)的, 所以我们只需要把usedSize置为0即可. 但是如果数组中存放的时引用类型,那么即使将usedSize置为0,堆上存放的对象还是被栈上的变量引用着(但是这些对象没用了),这样的话就会造成内存泄漏,形成不必要的内存损失.

所以: 数组中如果存放的是引用类型, 需要先将数组元素置为null, 再将usedSize置为0.

java 复制代码
    public void clear() {
        usedSize = 0;
    }

以上就是本篇博客的全部内容啦,如果喜欢小编的文章,可以点赞,评论,收藏~

相关推荐
计算机学姐1 分钟前
基于SpringBoot+Vue的在线投票系统
java·vue.js·spring boot·后端·学习·intellij-idea·mybatis
一休哥助手16 分钟前
Redis 五种数据类型及底层数据结构详解
数据结构·数据库·redis
救救孩子把17 分钟前
深入理解 Java 对象的内存布局
java
落落落sss20 分钟前
MybatisPlus
android·java·开发语言·spring·tomcat·rabbitmq·mybatis
苏宸啊23 分钟前
顺序表及其代码实现
数据结构·算法
万物皆字节25 分钟前
maven指定模块快速打包idea插件Quick Maven Package
java
lin zaixi()26 分钟前
贪心思想之——最大子段和问题
数据结构·算法
夜雨翦春韭32 分钟前
【代码随想录Day30】贪心算法Part04
java·数据结构·算法·leetcode·贪心算法
我行我素,向往自由39 分钟前
速成java记录(上)
java·速成
一直学习永不止步1 小时前
LeetCode题练习与总结:H 指数--274
java·数据结构·算法·leetcode·数组·排序·计数排序