【Java 数据结构】顺序表

这篇具有很好参考价值的文章主要介绍了【Java 数据结构】顺序表。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java
篮球哥温馨提示:编程的同时不要忘记锻炼哦!

我们不过是普通人,只不过在彼此眼中闪闪发光


目录

1、什么是顺序表?

2、模拟实现ArrayList

2.1 模拟实现前的约定

2.2 构造方法

2.3 add方法

2.4 contains 方法

2.5 indexOf 方法

2.6 get 方法

2.7 set 方法

2.8 remove 方法

2.9 getSize 和 clear 方法

3、ArrayList 的学习

3.1 ArrayList的成员属性

3.2 ArrayList的构造方法

3.2.1 构造方法1

3.2.2 构造方法2

3.2.3 构造方法3 

3.3 ArrayList 的 add 方法

3.4 ArrayList的常用方法

4、ArrayList的使用

4.1 ArrayList的遍历

4.2 扑克牌例子

4.2.1 准备工作

4.2.2 买一副牌逻辑

4.2.3 洗牌逻辑

4.2.3 发牌逻辑(重点) 

4.2.4 测试整体逻辑


1、什么是顺序表?

这里运用博主之前写C语言实现顺序表中引用的一句话:

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

顺序表又可以分为动态存储的顺序表和静态存储的顺序表,基本上现在不会使用静态的,这里就不介绍静态的了,所谓动态,就是当顺序表满的时候会自动扩容!我们接着往下看:

在Java中官方提供了ArrayList类,底层也是用数组实现的顺序表。

那么今天我们不急着去解读ArrayList类,而是先凭借我们之前的学习面向对象的知识,以及C语言数据结构阶段顺序表的实现,尝试着模拟实现 ArrayList类,当然,Java提供的是一个泛型类,可以存放任意指定类型数据(基本数据类型除外) ,我们就不模拟的那么复杂,能基本实现一些常见方法就行,等模拟实现之后,我们再去阅读源码。


2、模拟实现ArrayList

2.1 模拟实现前的约定

我们约定 elem 是存放整型数据的数组,size 表示数组当前有效元素个数,DEFAULT_CAPACITY 容量值,那么就可以写出这样的代码:

public class MyArrayList {
    private int elem[]; //存放数据
    private int size; //数组有效元素个数
    private static final int DEFAULT_CAPACITY = 10; //约定容量
}

同时我们还要实现以下几个常用的方法:

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

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

public boolean contains(int toFind);// 判定是否包含某个元素

public int indexOf(int toFind);// 查找某个元素对应的位置

public int get(int pos);// 获取 pos 位置的元素

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

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

public int getSize()// 获取顺序表长度

public void clear();// 清空顺序表

其实还有很多方法,比如头插,尾删,但这些你实现了上面的,相信你自己也能解决的,现在我们就撸起袖子写代码吧:

2.2 构造方法

这里我们想一想, 如何设置我们的构造方法呢?如果用户想一开始的时候就自定义大小呢?如果不想自定义我们是不是要设置一个默认的大小?那么就可以写出下面两个构造方法:

// 无参构造方法,默认将数组容量设置成DEFAULT_CAPACITY
public MyArrayList() {
    this.elem = new int[DEFAULT_CAPACITY];
}
// 带参数构造方法,将数组容量设置成用户指定的容量
public MyArrayList(int capacity) throws IllegalCapacityException {
    // 检查指定容量是否非法
    if (capacity <= 0) {
        throw new IllegalCapacityException("设置非法容量");
    }
    this.elem = new int[capacity];
}

代码中的异常是我自定义的一个运行时异常,如果对异常还不了解的,可以看博主之前写的JavaSE系列文章,这里我就不再谈异常了。

2.3 add方法

private void capacity() {
    //将原数组扩大到2倍,利用Arrays.copyOf
    int len = getSize();
    this.elem = Arrays.copyOf(this.elem, len * 2);
}

// 新增元素,默认在数组最后新增
public void add(int data) {
    // 1.空间是否满了,满了则需要扩容
    if (getSize() == this.elem.length) {
        capacity(); //扩容
    }
    // 2.往数组最后位置新增元素
    // 3.有效数据自增1
    this.elem[this.size++] = data;
}

在写这个方法的时候,我们要注意数组如果满了就要增容,而增容这里我们用到 copyOf 方法,每次扩容2倍。

add方法重载,在pos位置新增:

// 在 pos 位置新增元素
public void add(int pos, int data) throws IllegalPosException {
    //1.检查pos下标的合法性(顺序表指定插入前面必须有元素,不能隔着插入)
    if (pos > getSize() || pos < 0) {
        throw new IllegalPosException("指定插入pos位置不合法");
    }
    //2.判断数组是否需要增容
    if (getSize() == this.elem.length) {
        capacity(); //扩容
    }
    //3.从pos位置的元素都往后移
    for (int i = this.size - 1; i >= pos; i--) {
        this.elem[i + 1] = this.elem[i];
    }
    //4.pos位置放入数据,size自增
    this.elem[pos] = data;
    this.size++;
}

这里图就不给大家画了,在博主数据结构C语言版本的时候已经有很详细了图解了,感兴趣的可以去看一看,大同小异。

这里我们直接来说第一个要注意的点,因为是顺序表,插入元素不能隔着元素插入,也就是你插入的位置前面必须要有元素!也就得出 pos 必须小于等于我们的有效元素个数!

而且 pos 的位置不能小于0!

接着就是判断扩容和中间插入需要挪动后面的元素了,过程很简单,这里就不多谈了。

2.4 contains 方法

// 判定是否包含某个元素
public boolean contains(int toFind) {
    //1.遍历数组
    for (int i = 0; i < getSize(); i++) {
        if (this.elem[i] == toFind) {
            return true; //2.找到返回true
        }
    }
    //3.找不到返回false
    return false;
}

这个方法就太简单了,看我写的注释就能看懂!

2.5 indexOf 方法

// 查找某个元素对应的位置
public int indexOf(int toFind) {
    //1.遍历数组
    for (int i = 0; i < getSize(); i++) {
        if (this.elem[i] == toFind) {
            return i; //2.找到返回下标
        }
    }
    //3.找不到返回-1
    return -1;
}

这个方法跟上面contains方法大同小异,无需多言!

2.6 get 方法

// 获取 pos 位置的元素
public int get(int pos) {
    //1.判断pos位置是否合法
    if (pos > getSize() || pos < 0) {
        throw new IllegalPosException("获取pos位置不合法");
    }
    //2.返回pos位置值
    return this.elem[pos];
}

这个方法需要注意的点就是判断pos下标位置的合法性,注意这一点就ok了!

2.7 set 方法

// 给 pos 位置的元素设为 value
public void set(int pos, int value) {
    //1.判断pos位置是否合法
    if (pos > getSize() || pos < 0) {
        throw new IllegalPosException("pos位置不合法");
    }
    //2.设置值
    this.elem[pos] = value;
}

好像跟上面的 get 方法没什么区别唉,多简单就不用我多说了吧!

2.8 remove 方法

//删除第一次出现的关键字key
public void remove(int toRemove) {
    //1.获取第一次key出现的位置
    int pos = indexOf(toRemove);
    if (pos == -1) {
        return;
    }
    //2.从pos位置的元素都往前覆盖
    for (int i = pos + 1; i < getSize(); i++) {
        this.elem[i - 1] = this.elem[i];
    }
    //3.有效数据减一(如果是引用类型需要置null)
    this.size--;
}

这个方法我们就可以复用我们之前写的 indexOf 方法了,不用重新写查找逻辑了,接着把后面的元素覆盖掉 pos 下标的元素就可以了!记得别忘记有效数据减一哦!

2.9 getSize 和 clear 方法

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

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

这两个就简单了吧,但是要注意一点,如果你的顺序表放的是引用类型,需要置null,方法已经实现的差不多了,感兴趣的下来结合代码画图写一写吧!


3、ArrayList 的学习

3.1 ArrayList的成员属性

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

  • ArrayList实现了RandomAccess接口,表明ArrayList支持随机访问
  • ArrayList实现了Cloneable接口,表明ArrayList是可以clone的
  • ArrayList实现了Serializable接口,表明ArrayList是支持序列化的 

这就是类定义的前部分,这里还是比较复杂的,会随着我们学习的深入,逐步学习到。

接下来我们来看ArrayList的几个成员变量:

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

3.2 ArrayList的构造方法

3.2.1 构造方法1

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

当前是一个带参数的构造方法,很好理解,根据传递的参数开辟大小,如果参数是等于0,就直接把 EMPTY_ELEMENTDATA 共享空数组赋值给存放数据的数组中, 如果是给定一个负数,显然是错误的,也即直接抛出异常!

3.2.2 构造方法2

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

奇怪,这个无参构造方法居然也是给了一个空数组,也就是没有分配数组内存,那到底是怎么把数据放进去的呢?别急,随着后面的讲解,你会解开这个谜题。

3.2.3 构造方法3 

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

按照集合迭代器返回元素的顺序,构造一个包含指定集合元素的列表,如果是属于同类型,就直接放入到存放数据的数组中,如果不是同类型,则利用 copyOf 拷贝指定的集合,如果指定集合长度为0,则把 EMPTY_ELEMENTDATA 共享空数组赋值给存放数据的数组中。

这个地方如果你不是很理解,没关系,因为现在还没接触迭代器,随着学习的深入就会接触到。

3.3 ArrayList 的 add 方法

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

别小看这几行代码,跟我们自己模拟实现的还是有区别的,真正有内涵的代码其实在 ensureCapacityInternal 这个方法中,那么现在,我们就一步步去解开他的面纱:

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java有了上面的图解我们不难看出,真正的扩容是在 add 方法中实现的,所以在实例化 ArrayList 的时候,是不会默认给你开辟空间的。所以 ArrayList 默认容量是在 add 方法调用后,才会分配空间。而且在真正扩容之前会检测是否能扩容成功,防止太大导致扩容失败。

3.4 ArrayList的常用方法

方法 作用
boolean add(E e) 尾插 e
void add(int index, E element) 将 e 插入到 index 位置
boolean addAll(Collection c) 尾插 c 中的元素
E remove(int index) 删除 index 位置元素
boolean remove(Object o) 删除遇到的第一个 o
E get(int index) 获取下标 index 位置元素
E set(int index, E element) 将下标 index 位置元素设置为 element
void clear() 清空顺序表
boolean contains(Object o) 判断 o 是否在线性表中
int indexOf(Object o) 返回第一个 o 所在下标
int lastIndexOf(Object o) 返回最后一个 o 的下标
List subList(int fromIndex, int toIndex) 截取部分 list

还有其他方法需要使用的话,就可以去查阅Java的帮助文档,到了数据结构阶段,就要尝试着自己看源码,看文档了,培养自主学习的能力!


4、ArrayList的使用

4.1 ArrayList的遍历

对于顺序表的遍历,我们可以通过 for 循环,for-each,以及迭代器的方法遍历:

public class TestArrayList {
    public static void main(String[] args) {
        ArrayList<Integer> arrayList = new ArrayList<>();
        arrayList.add(1);
        arrayList.add(2);
        arrayList.add(3);
        // 通过for循环遍历ArrayList
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.print(arrayList.get(i) + " ");
        }
        // 通过for-each循环遍历ArrayList
        for (Integer integer : arrayList) {
            System.out.print(integer + " ");
        }
        // 通过迭代器遍历ArrayList(了解即可)
        Iterator<Integer> it = arrayList.iterator();
        while (it.hasNext()) {
            System.out.print(it.next() + " ");
        }
    }
}

4.2 扑克牌例子

这里我们要运用我们上面学的知识写一个扑克牌的例子:

4.2.1 准备工作

首先我们肯定有一个类把我们的一张扑克抽象出来,扑克有花色和点数,那么我们就可以这样写:

public class Poker {
    private String decor;
    private int number;

    public Poker(String decor, int number) {
        this.decor = decor;
        this.number = number;
    }

    @Override
    public String toString() {
        return this.decor + this.number;
    }
}

那么我们还得需要表示多张扑克牌,同时也需要一个存放扑克牌的容器,这里我们选用 ArrayList,同时还需要一个数组来存储对应花色。

public class Pokers {
    private final String[] decor = { "♥", "♠", "♣", "♦" };
    private List<Poker> pokerList = new ArrayList<>();

    // 获取花色
    public String get(int index) {
        return decor[index];
    }
}

这里为什么可以使用 List 接收 ArrayList 的对象呢?因为 List 是一个接口,ArrayList 实现了这个接口,所以这里就实现了向上转型

4.2.2 买一副牌逻辑

准备工作都做好了,我们要实现买一副牌的逻辑,除了大小王一共有52张牌,我们这里用11 12 13 代替 J Q K,每张牌一共有四种花色,也就是定义一个双层循环遍历放入到我们的容器中即可,最后在放入我们的大小王,这里不涉及太复杂,就定大小王的点数为0!

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

4.2.3 洗牌逻辑

买一副扑克牌的逻辑写好了,那么现在就应该洗牌了,那么洗牌应该怎么去实现他呢?

我们可以运用 Random 类中产生随机数方法,但是产生了随机数,如何打乱牌呢?

如果从最后一个开始洗,即 last 位置开始,产生 last 的随机数是 [0~last) ,不包含last,所以我们可以从后往前洗牌,每次把最后一张牌与产生的随机数位置的牌交换即可。(不考虑业务性)

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

4.2.3 发牌逻辑(重点) 

如何去模拟实现发牌呢?一共有三个人打牌,每个人轮流摸牌,如果是54张牌要摸18轮,摸到的牌是不是也应该放到对应的人手上,站在编程的角度,应该摸到的牌应该放在对应那个人的容器中。

如何表示我们上述的设想呢?假设我们有一个顺序表,一共三个元素,分别代表三个人,而每个元素里面又放着一个顺序表,而这个顺序表对应着这个人摸到的牌!我们就能画出这样的图:

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

通过图我们想一想,这个结构不就是有一个ArrayList吗?然后ArrayList里面放的元素类型还是ArrayList,我们要传什么实参类型进去呢?当然是Poker了啊,因为里面的ArrayList最后是要放扑克牌的!于是我们就能写出这样的代码:

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

这里我们要说一点,发牌的时候,每次都是删除第一张牌,并且把删除的第一张牌增加到对应用户的手牌中,这样也就形成了摸牌逻辑,最后把牌打印出来就好了!

4.2.4 测试整体逻辑

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

最终我们在main方法中调用如上的 testGame方法实现的是这样一个效果:

数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

到这就实现的差不多啦!买牌,洗牌,发牌逻辑都没问题,这个小练习,不涉及业务,我们主要是把学习的顺序表知识运用起来,听博主一句话,学数据结构,多敲代码多画图!


数据结构java顺序表基本算法测试,Java数据结构,数据结构,顺序表,算法,java

下期预告:【Java 数据结构】单链表与OJ题文章来源地址https://www.toymoban.com/news/detail-828834.html

到了这里,关于【Java 数据结构】顺序表的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构:定长顺序串(SString)基本操作的算法描述(C语言)

    作者在学习数据结构时,发现鲜有完全按照 C 语言描述的算法操作,这让习惯于写 .c 而不是 .cpp 的初学者很是头疼。本文将基于 C 语言描述算法操作,如有错漏还望大佬们指正。 本文将按照严惠敏所著《数据结构(C语言版)》所做的函数原型声明进行算法描述,由于C语言不支

    2024年02月07日
    浏览(69)
  • 【Java 数据结构】顺序表

    篮球哥温馨提示:编程的同时不要忘记锻炼哦! 目录 1、什么是顺序表? 2、模拟实现ArrayList 2.1 模拟实现前的约定 2.2 构造方法 2.3 add方法 2.4 contains 方法 2.5 indexOf 方法 2.6 get 方法 2.7 set 方法 2.8 remove 方法 2.9 getSize 和 clear 方法 3、ArrayList 的学习 3.1 ArrayList的成员属性 3.2 Arr

    2024年02月20日
    浏览(31)
  • 《Java数据结构入门》顺序表详解

     大家好,我是小鱼儿 目录 顺序表介绍: 顺序表的手动实现 顺序表功能接口概览 基本功能的实现 四大功能 一、增加数据  二、删除数据 三、查找数据 四、修改数据  总代码 MyArraysList.java  Test.java 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一

    2023年04月18日
    浏览(33)
  • [JAVA数据结构]顺序表ArrayList

    目录 1.线性表 2.顺序表 3.ArrayList简介 4.ArrayList的使用  4.1ArrayList的构造方法 4.2ArrayList的常用操作 4.3ArrayList的遍历方法 4.4ArrayList的扩容机制 5.ArrayList的具体运用 ArrayList是一种基于数组的数据结构,是线性表的一种,也是顺序表。 通俗来说,线性表是一种线性结构,在逻辑上

    2023年04月26日
    浏览(40)
  • 数据结构 之 顺序表 ArrayList (Java)

    🎉欢迎大家观看AUGENSTERN_dc的文章(o゜▽゜)o☆✨✨ 🎉感谢各位读者在百忙之中抽出时间来垂阅我的文章,我会尽我所能向的大家分享我的知识和经验📖 🎉希望我们在一篇篇的文章中能够共同进步!!! 🌈个人主页: AUGENSTERN_dc 🔥个人专栏: C语言  |  Java | 数据结构 ⭐个

    2024年03月17日
    浏览(34)
  • 数据结构(Java实现)-ArrayList与顺序表

    什么是List List是一个接口,继承自Collection。 List的使用 List是个接口,并不能直接用来实例化。 如果要使用,必须去实例化List的实现类。在集合框架中,ArrayList和LinkedList都实现了List接口。 线性表 线性表(linear list)是n个具有相同特性的数据元素的有限序列。 常见的线性表

    2024年02月11日
    浏览(36)
  • 【Java数据结构】顺序表、队列、栈、链表、哈希表

    是一个有类型参数(type parameter)的范型表(generic class) 能够自动调整容量,并且不需要写额外的代码 存放数据使用数组但是可以编写一些额外的操作来强化为线性表,底层依然采用顺序存储实现的线性表,称为顺序表 创建 常见操作 一旦确认数组列表大小恒定,不再发生

    2024年02月02日
    浏览(41)
  • 【C++】【数据结构】循环队列的基本操作(初始化、入队、出队、取队头元素、遍历输出队列、求队列长度)顺序队列的算法实现【附全代码】

    使用c++完成数据结构循环队列的基本操作,包括(初始化、入队、出队、取队头元素、遍历输出队列、求队列长度等),可直接编译运行。 队列 又称为 “先进先出” (FIFO)线性表。限定插入操作只能在队尾进行,而删除操作只能在队首进行。 循环队列 ——采用 顺序存储结构

    2023年04月16日
    浏览(51)
  • 数据结构-树的遍历和基本操作(Java实现)

    二叉树的遍历分为以下三种:  前序遍历: 访问顺序为  根节点----左子树----右子树 中序遍历: 访问顺序为  左子树----根节点----右子树 后序遍历: 访问顺序为  左子树----右子树----根节点 接下来针对这3种遍历方式进行详细介绍: 上图前序遍历顺序为 1 2 3 4 5 6 上图中序遍历顺序

    2024年03月25日
    浏览(43)
  • 【数据结构】顺序表基本操作的实现(C语言)

    🚀 作者简介:一名在后端领域学习,并渴望能够学有所成的追梦人。 🐌 个人主页:蜗牛牛啊 🔥 系列专栏:🛹数据结构、🛴C++ 📕 学习格言:博观而约取,厚积而薄发 🌹 欢迎进来的小伙伴,如果小伙伴们在学习的过程中,发现有需要纠正的地方,烦请指正,希望能够与

    2024年02月16日
    浏览(53)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包