Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列)

这篇具有很好参考价值的文章主要介绍了Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

🔥博客主页: 【小扳_-CSDN博客】
❤感谢大家点赞👍收藏⭐评论✍
 

Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列),Java 数据结构与算法篇,数据结构,链表,java,算法

Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列),Java 数据结构与算法篇,数据结构,链表,java,算法

文章目录

        1.0 队列的说明

        1.1 队列的几种常用操作

        2.0 使用链表实现队列说明

        2.1 链表实现队列

        2.2 链表实现队列 - 入栈操作

        2.3 链表实现队列 - 出栈操作

        2.4 链表实现队列 - 获取队头元素操作(不删除)

        2.5 链表实现队列 - 获取队列有效元素个数操作

        2.6 链表实现队列 - 判空处理操作

        2.7 用链表实现队列的完整代码

        3.0 使用数组实现循环队列说明

        3.1 数组实现循环队列的操作

        3.2 数组实现循环队列 - 入队列操作

        3.3 数组实现循环队列 - 出队列操作

        3.4 数组实现队列 - 得到队头元素操作(不删除)

        3.5 数组实现队列 - 得到队尾元素操作(不删除)

        3.6 数组实现队列 - 判空队列操作

        3.7 数组实现队列 - 判满队列操作

        3.8 用数组实现队列完整代码


        1.0 队列的说明

        队列是一种线性数据结构,具有先进先出First In First Out,FIFO)的特性。它类似于排队的概念,新元素被添加到队列的尾部而从队列中移除元素时则从队列的头部开始。队列通常用于需要按照特定顺序处理元素的场景,比如任务调度、消息传递等。

        1.1 队列的几种常用操作

                - 队首元素(front):队列的头部元素。

                - 队尾元素(rear):队列的尾部元素。

                - 入队(offer):将新元素添加到队列的尾部。

                - 出队(poll):从队列的头部移除元素。

                - 获取队头元素(peek):从队列的头部获取元素,不移除。

                - 判空(isEmpty):判断队列是否为空。

                - 判满(isFull):判断队列是否已满(对于有限大小的队列)。

                - 元素个数(size):获取队列有效的元素个数。

接口代码如下:

public interface QueueInterface{
    /**
     * 入列
     */
    boolean offer(int e);

    /**
     * 出列
     */
    int poll();

    /**
     * 获取队列头元素
     */
    int peek();

    /**
     * 获取队列中有效元素个数
     */
    int size();

    /**
     * 检验队列是否为空
     */
    boolean isEmpty();
}

        2.0 使用链表实现队列说明

        使用链表实现队列,无疑就是用链表的数据结构的方式来实现队列的操作(实现队列的接口)。跟栈不同的是:栈只能对一端进行操作,而队列是对头尾进行操作。一般对于单链表来说,头节点当作队列中的队头(front)尾节点当作队列中的队尾(rear)。而入队列相当于尾插,在链表尾部插入节点,出队列相当于头删,在链表头部删除头节点。对于双向链表来说,就比较自由了,头节点既可以作为队头,也可以作为队尾。尾节点既可以作为队头,也可以作为队尾。

        2.1 链表实现队列

        用双向链表来实现队列,既然头尾都可以作为队列,选其中一种即可,对于队尾来说也是如此。这里就用头节点作为队列中的队头,而尾节点作为队列中的队尾。

简单分析:

        - 实现入栈操作:在链表尾部插入节点即可。

        - 实现出栈操作:在链表头部删除节点即可。

        - 实现获取队列头部元素:获取链表头部节点的元素即可。

        - 实现总计有效元素个数:需要定义一个成员变量 size ,入栈时进行 size++ ,出栈时  size--

        - 实现判空处理:当 size == 0 ,则为空队列。

        - 实现判断满队列:当 size >= 创建队列时默认大小,则为满队列。

        2.2 链表实现队列 - 入栈操作

                实现入栈操作:在链表尾部插入节点即可。分为两种情况:当队列为空时,则入栈的节点即是队头也是队尾当队列不为空时,则入栈的节点一般来说就是新的队尾。每一次入栈完成后,都需要进行 size++

代码如下:

    //入列
    @Override
    public boolean offer(int e) {
        if (isEmpty()) {
            front = rear = new Node(null,e,null);
            size++;
            return true;
        }
        Node node = new Node(rear,e,null);
        rear.next = node;
        rear = node;
        size++;
        return true;
    }

        2.3 链表实现队列 - 出栈操作

                实现出栈操作:在链表头部删除节点即可。出栈一般分为三种情况:

        第一种情况,当队列为空时,不应该出栈了,直接返回 -1 或者抛异常。

        第二种情况,当只有一个节点时,出栈之后,就不会再有元素了,所以 frontrear 需要置为空。返回出栈节点的值即可。

        第三种情况,除了第一、二种情况之后,第三种情况就可以正常的进行头删节点操作处理了。需要注意的是,出栈完成后,进行 size-- 。最后,返回出栈节点的数值即可。

代码如下:

 文章来源地址https://www.toymoban.com/news/detail-752290.html

    //出列
    @Override
    public int poll() {
        if (isEmpty()){
            return -1;
        }
        //注意特例:只有一个节点的情况
        if (front.next == null) {
            int temp = front.val;
            front = null;
            rear = null;
            return temp;
        }
        Node temp = front;
        front = front.next;
        front.prev = null;
        size--;
        return temp.val;
    }

        2.4 链表实现队列 - 获取队头元素操作(不删除)

                获取链表头部节点的元素即可。一般分为两种情况:当队列为空时,可以返回 -1 或者抛异常处理当队列不为空时,直接返回头部节点的值即可

代码如下:

    @Override
    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return front.val;
    }

        2.5 链表实现队列 - 获取队列有效元素个数操作

                直接返回 size 即可。

    @Override
    public int size() {
        return size;
    }

        2.6 链表实现队列 - 判空处理操作

                size == 0 时,返回 true 。否则返回 false 。也可以用 front == null 来判断是否为空队列。

代码如下:

    @Override
    public boolean isEmpty() {
        return front == null;
    }

 

        2.7 用链表实现队列的完整代码

public class MyLinkedQueue implements QueueInterface {

    static class Node {
        public Node prev;
        public int  val;
        public Node next;

        public Node(Node prev, int val, Node next) {
            this.prev = prev;
            this.val = val;
            this.next = next;
        }
    }

    private Node front;
    private Node rear;
    private int size;

    //入列
    @Override
    public boolean offer(int e) {
        if (isEmpty()) {
            front = rear = new Node(null,e,null);
            size++;
            return true;
        }
        Node node = new Node(rear,e,null);
        node.prev = rear;
        rear.next = node;
        rear = node;
        size++;
        return true;
    }

    //出列
    @Override
    public int poll() {
        if (isEmpty()){
            return -1;
        }
        //注意特例:只有一个节点的情况
        if (front.next == null) {
            int temp = front.val;
            front = null;
            rear = null;
            return temp;
        }
        Node temp = front;
        front = front.next;
        front.prev = null;
        size--;
        return temp.val;
    }

    @Override
    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return front.val;
    }

    @Override
    public int size() {
        return size;
    }

    @Override
    public boolean isEmpty() {
        return front == null;
    }

}

 

        3.0 使用数组实现循环队列说明

        用数组实现队列,一般来说是循环队列,循环队列可以解决普通队列在出队操作后产生的空间浪费问题,同时可以利用数组的固定大小来实现队列的循环利用。

循环队列的接口代码如下:

public interface QueueInterface{
    /**
     * 入列
     */
    boolean offer(int e);

    /**
     * 出列
     */
    int poll();

    /**
     * 获取队列头元素,不删除
     */
    int peek();
    
    /**
     * 检验队列是否为空
     */
    boolean isEmpty();

    /**
     * 判断是否为满队列
     */
    boolean isFull();

    /**
     * 得到队尾元素,不删除
     */
    int Rear();
}

        使用数组实现队列,无疑就是用数组的数据结构的方式来实现队列的操作(实现队列的接口)。循环队列的关键是使用两个指针来标记队列的头部和尾部,分别称为 front rear 当入队时,rear 指针向后移动当出队时,front 指针向后移动。当 rear 指针到达数组的末尾时,可以通过取模运算将 rear 指针置为 0 ,实现循环的效果。

        3.1 数组实现循环队列的操作

                - 入队操作:将元素添加到 rear 指针所指向的位置,并更新 rear 指针。

                - 出队操作:front 指针所指向的位置移除元素,并更新 front 指针。

                - 判空操作:front 指针等于 rear 指针时,队列为空。

                - 判满操作: (rear+1) % 数组长度等于 front 指针时,队列为满。

        3.2 数组实现循环队列 - 入队列操作

                将元素添加到 rear 指针所指向的位置,并更新 rear 指针。更新 rear 就是往后走一步,但是为了实现循环,可不能简单的进行 +1 处理,需要 rear = (rear + 1) % arr.length,这样就可以数组中循环走了。在入队前,需要先判断是否为满队列了。

代码如下:

    // 入队列
    @Override
    public boolean offer(int e) {
        if (isFull()) {
            return false;
        }
        arr[rear] = e;
        rear = (rear+1) % arr.length;
        return true;
    }

         3.3 数组实现循环队列 - 出队列操作

                front 指针所指向的位置移除元素,并更新 front 指针。同样的,更新可不能简单的 +1 处理,需要将 front = (front + 1) % arr.length ,每次出栈前需要记录一下出栈的元素,接着才往后走,最后返回记录的元素即可。出栈前,需要判断是否为空队列,如果为空队列,就需要抛异常或者返回 -1 处理。

代码如下:

    //出队列
    @Override
    public int poll() {
        if (isEmpty()) {
            return -1;
        }
        int temp = arr[front];
        front = (front + 1) % arr.length;
        return temp;
    }

        3.4 数组实现队列 - 得到队头元素操作(不删除)

                先判断是否为空队列,若不是,则返回队头元素即可。

代码如下:

    //得到队头元素,不删除
    @Override
    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return arr[front];
    }

         3.5 数组实现队列 - 得到队尾元素操作(不删除)

                先判断队列是否为空,如果为空队列,则返回 -1 或者抛异常。如果不为空,则需要返回 arr[rear - 1],但是需要注意的是:有一种情况需要额外考虑进去,当 rear == 0 时,那么 rear - 1 == -1 所以不合理,数组中的索引不存在 -1 。因此这个情况要分开讨论,当 rear == 0 时,那么需要返回的值为 arr[arr.length - 1]当 rear != 0 时,那么返回的值为 arr[rear - 1]

代码如下:

    //得到队尾元素,不删除
    @Override
    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        int temp = (rear == 0) ? arr.length - 1 : rear - 1;
        return arr[temp];
    }

        3.6 数组实现队列 - 判空队列操作

                当且仅当 rear == front 时,则队列为空

代码如下:

    @Override
    public boolean isEmpty() {
        return front == rear;
    }

        3.7 数组实现队列 - 判满队列操作

                有很多种方式可以来判断队列是否满,比如,定义 size 变量来总计元素个数,然后跟 arr.lengrh 进行对比,相等即满队列了,不相等即为还没有满队列使用标记也可以实现判断是否为满队列。

        这里介绍牺牲空间来判断满队列,即当且仅当 (rear + 1) % arr.lengrh == front 时,该队列满了。由于这里牺牲了一个空间,所以需要在自定义初始化数组大小的时候额外 +1

代码如下:

    // 自定义数组大小
    public ArrayQueue(int capacity) {
        arr = new int[capacity + 1];
    }

    // 默认数组大小为: 10
    public ArrayQueue() {
        arr = new int[10];
    }
    @Override
    //判断是否为满队列(有很多种判断方法,这里使用牺牲空间方法来判断)
    public boolean isFull() {
        return (rear + 1) % arr.length == front;
    }

        3.8 用数组实现队列完整代码

public class ArrayQueue implements QueueInterface{

    private int front;
    private int rear;
    private int[] arr;

    // 自定义数组大小
    public ArrayQueue(int capacity) {
        arr = new int[capacity + 1];
    }

    // 默认数组大小为: 10
    public ArrayQueue() {
        arr = new int[10];
    }

    // 入队列
    @Override
    public boolean offer(int e) {
        if (isFull()) {
            return false;
        }
        arr[rear] = e;
        rear = (rear+1) % arr.length;
        return true;
    }

    //出队列
    @Override
    public int poll() {
        if (isEmpty()) {
            return -1;
        }
        int temp = arr[front];
        front = (front + 1) % arr.length;
        return temp;
    }

    //得到队头元素,不删除
    @Override
    public int peek() {
        if (isEmpty()) {
            return -1;
        }
        return arr[front];
    }

    //得到队尾元素,不删除
    @Override
    public int Rear() {
        if (isEmpty()) {
            return -1;
        }
        int temp = (rear == 0) ? arr.length - 1 : rear - 1;
        return arr[temp];
    }

    @Override
    public boolean isEmpty() {
        return front == rear;
    }

    @Override
    //判断是否为满队列(有很多种判断方法,这里使用牺牲空间方法来判断)
    public boolean isFull() {
        return (rear + 1) % arr.length == front;
    }
    
}

Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列),Java 数据结构与算法篇,数据结构,链表,java,算法

 

到了这里,关于Java 数据结构篇-用链表、数组实现队列(数组实现:循环队列)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 【数据结构和算法】使用数组的结构实现链表(单向或双向)

    上文我们通过结构体的结构实现了队列 、以及循环队列的实现,我们或许在其他老师的教学中,只学到了用结构体的形式来实现链表、队列、栈等数据结构,本文我想告诉你的是,我们 可以使用数组的结构实现链表、单调栈、单调队列 目录 前言 一、用数组结构的好处 1.数

    2024年01月20日
    浏览(74)
  • Java常见的数据结构:栈、队列、数组、链表、二叉树、二叉查找树、平衡二叉树、红黑树

    数据结构是计算机底层存储、组织数据的方式。是指数据相互之间是以什么方式排列在一起的。 通常情况下,精心选择的数据结构可以带来更高的运行或者存储效率 栈 队列 数组 链表 二叉树 二叉查找树 平衡二叉树 红黑树... 后进先出,先进后出 数据进入栈模型的过程称为

    2024年02月07日
    浏览(45)
  • 数据结构——链表的实现(Java版)

    目录 一、链表 二、代码实现 1.创建结点 2.构造函数 3.链表的相关属性 4.添加虚拟节点 5.判断链表是否为空 6.添加方法 (1)在头部添加 (2)在尾部添加 (3)在索引位置添加 (4)对头插法和尾插法代码进行简化(调用任意位置添加的方法) 7.打印链表(遍历,重写toString方

    2024年01月23日
    浏览(49)
  • 数据结构——线性数据结构(数组,链表,栈,队列)

    数组(Array) 是一种很常见的数据结构。它由相同类型的元素(element)组成,并且是使用一块连续的内存来存储。 我们直接可以利用元素的索引(index)可以计算出该元素对应的存储地址。 数组的特点是: 提供随机访问 并且容量有限。 2.1. 链表简介 链表(LinkedList) 虽然是

    2024年02月11日
    浏览(44)
  • 数据结构(Java实现)LinkedList与链表(上)

    链表 逻辑结构 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。 无头双向链表:在Java的集合框架库中LinkedList底层实现就是无头双向循环链表。 链表的实现 创建一个链表 遍历单链表 、 得到

    2024年02月11日
    浏览(52)
  • 数据结构(Java实现)LinkedList与链表(下)

    ** ** 结论 让一个指针从链表起始位置开始遍历链表,同时让一个指针从判环时相遇点的位置开始绕环运行,两个指针都是每次均走一步,最终肯定会在入口点的位置相遇。 LinkedList的模拟实现 单个节点的实现 尾插 运行结果如下: 也可以暴力使用 全部代码 MyLinkedList IndexOut

    2024年02月11日
    浏览(45)
  • 数据结构——用Java实现数组

    数据结构是一门基础的学科,是研究数据如何在计算机中进行组织和存储,使得我们可以高效的获取数据和修改数据的。 1.线性结构:数组、队列、栈、链表、哈希表… 2.树形结构:二叉树、二分搜索树、AVL树,红黑树、堆、Trie、线段树、并查集… 3.图结构:邻接矩阵、邻接

    2024年01月18日
    浏览(47)
  • 【数据结构与算法——TypeScript】数组、栈、队列、链表

    解决问题 的过程中,不仅仅 数据的存储方式会影响效率,算法的优劣也会影响效率 什么是算法? 定义: 🟢 一个有限指令集,每条指令的描述不依赖于言语 (编写指令:java/c++/ts/js) 🟢 接收一些输入(有些情况下不需要输入)(接收:排序:无序数组) 🟢 产生输出 (

    2024年02月14日
    浏览(38)
  • 【数据结构与算法】1、学习动态数组数据结构(基本模拟实现 Java 的 ArrayList 实现增删改查)

    🍃 数据结构是 计算机 存储 、 组织 数据的方式 🎉 线性 结构 线性表(数组、链表、栈、队列、哈希表) 🎉 树形 结构 二叉树 AVL 树 红黑树 B 树 堆 Trie 哈夫曼树 并查集 🎉 图形 结构 邻接矩阵 邻接表 🎁 线性表是具有 n 个 相同类型元素 的有限 序列 (n = 0) a1 是首节点

    2024年02月10日
    浏览(77)
  • Java 数据结构篇-用数组、堆实现优先级队列

    🔥博客主页: 【 小扳_-CSDN博客】 ❤感谢大家点赞👍收藏⭐评论✍    文章目录         1.0 优先级队列说明         2.0 用数组实现优先级队列         3.0 无序数组实现优先级队列         3.1 无序数组实现优先级队列 - 入队列 offer(E value)         3.2 无序数组实现优先

    2024年02月04日
    浏览(45)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包