基础数据结构——队列(链表实现,数组实现)

news2024/10/26 17:16:49

1.概述

计算机科学中,queue 是以顺序的方式维护的一组数据集合,在一端添加数据,从另一端移除数据。习惯来说,添加的一端称为,移除的一端称为,就如同生活中的排队买商品

接口信息如下

public interface Queue<E> {
    //向队列尾部添加值
    boolean offer(E value);

    //从队列头部获取值并移除
    E poll();

    //从队列头部获取值不移除
    E peek();

    //判断队列是否为空
    boolean isEmpty();

    //判断队列是否已满
    boolean isFull();
}

2.单向环形链表(带哨兵)实现队列

在这里插入图片描述

public class LinkedListQueue<E> implements Queue<E>, Iterable<E> {
    private Node<E> head = new Node<>(null, null);//定义头节点哨兵
    private Node<E> tail = head;//定义尾节点指针
    private int size;//队列长度
    private int capacity = 8;//容量

    public LinkedListQueue() {
        this.tail.next = head;
    }

    public LinkedListQueue(int capacity) {
        this.tail.next = head;
        this.capacity = capacity;
    }

    @Override
    public boolean offer(E value) {
        if (isFull()) {
            return false;
        }
        Node<E> add = new Node<>(value, head);
        tail.next = add;
        tail = add;
        size++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        Node<E> first = head.next;
        head.next = first.next;
        if (first == tail) {
            tail = head;
        }
        size--;
        return first.value;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return head.next.value;
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return capacity == size;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            Node<E> pointer = head.next;

            @Override
            public boolean hasNext() {
                return pointer != head;
            }

            @Override
            public E next() {
                E value = pointer.value;
                pointer = pointer.next;
                return value;
            }
        };
    }

    /**
     * 定义节点类
     */
    private static class Node<E> {
        private E value;
        private Node<E> next;

        public Node(E value, Node<E> next) {
            this.value = value;
            this.next = next;
        }
    }
}

3.环形数组实现队列

好处
  1. 对比普通数组,起点和终点更为自由,不用考虑数据移动
  2. “环”意味着不会存在【越界】问题
  3. 数组性能更佳
  4. 环形数组比较适合实现有界队列、RingBuffer 等

在这里插入图片描述下标计算

例如,数组长度是 5,当前位置是 3 ,向前走 2 步,此时下标为 ( 3 + 2 ) % 5 = 0 (3 + 2)\%5 = 0 (3+2)%5=0
在这里插入图片描述

( c u r + s t e p ) % l e n g t h (cur + step) \% length (cur+step)%length

  • cur 当前指针位置
  • step 前进步数
  • length 数组长度

注意:

  • 如果 step = 1,也就是一次走一步,可以在 >= length 时重置为 0 即可

判断空
在这里插入图片描述

判断满
在这里插入图片描述满之后的策略可以根据业务需求决定

  • 例如我们要实现的环形队列,满之后就拒绝入队
public class ArrayQueue<E> implements Queue<E>, Iterable<E> {
    private int head = 0;//起始指针
    private int tail = 0;//终点指针
    private E[] array;//数组数据

    @SuppressWarnings("all")
    public ArrayQueue(int capacity) {
        this.array = (E[]) new Object[capacity + 1];
    }

    @Override
    public boolean offer(E value) {
        if (isFull()) {
            return false;
        }
        array[tail] = value;
        //tail++;
        tail = (tail + 1) % array.length;
        return true;
    }

    @Override
    public E poll() {
        if(isEmpty()){
            return null;
        }
        E value = array[head];
        //head++;
        head = (head + 1) % array.length;
        return value;
    }

    @Override
    public E peek() {
        if(isEmpty()){
            return null;
        }
        return array[head];
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        //return tail + 1 == head;
        return (tail + 1) % array.length == head;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int index = head;

            @Override
            public boolean hasNext() {
                return index != tail;
            }

            @Override
            public E next() {
                E value = array[index];
                index = (index + 1) % array.length;
                return value;
            }
        };
    }
}

引入size变量

public class ArrayQueue2<E> implements Queue<E>, Iterable<E> {
    private int head = 0;//起始指针
    private int tail = 0;//终点指针
    private E[] array;//数组数据
    private int size = 0;//数组大小

    @SuppressWarnings("all")
    public ArrayQueue2(int capacity) {
        this.array = (E[]) new Object[capacity];
    }

    @Override
    public boolean offer(E value) {
        if (isFull()) {
            return false;
        }
        array[tail] = value;
        tail = (tail + 1) % array.length;
        size++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        E value = array[head];
        head = (head + 1) % array.length;
        size--;
        return value;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return array[head];
    }

    @Override
    public boolean isEmpty() {
        return size == 0;
    }

    @Override
    public boolean isFull() {
        return array.length == size;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int pointer = head;
            int count = 0;

            @Override
            public boolean hasNext() {
                return size > count;
            }

            @Override
            public E next() {
                E value = array[pointer];
                pointer = (pointer + 1) % array.length;
                count++;
                return value;
            }
        };
    }
}

优化

public class ArrayQueue3<E> implements Queue<E>, Iterable<E> {
    /*
        求模运算:
        - 如果除数是 2 的 n 次方
        - 那么被除数的后 n 位即为余数 (模)
        - 求被除数的后 n 位方法: 与 2^n-1 按位与
     */
    private int head = 0;//起始指针
    private int tail = 0;//终点指针
    private final E[] array;//数组数据

    @SuppressWarnings("all")
    public ArrayQueue3(int capacity) {
        /**
         * capacity必须是 2的 n次方
         * 1.抛异常
         * 2.改成2的n次方
         *      1.找到比 capacity 大的最接近的 2 的 n 次方
         */
        /*if((capacity & capacity - 1) != 0){
            throw new IllegalArgumentException("capacity必须是2的幂");
        }*/
        /*
            2^4     = 16
            2^4.?   = 30
            2^5     = 32

              (int)log2(30) + 1
            2

            log2(x) = log10(x) / log10(2)

            1
            10      2^1
            100     2^2
            1000    2^3
         */
        capacity = 1 << (int) (Math.log10(capacity - 1) / Math.log10(2)) + 1;
        this.array = (E[]) new Object[capacity];
    }

    @Override
    public boolean offer(E value) {
        if (isFull()) {
            return false;
        }
        array[tail & array.length - 1] = value;
        tail++;
        return true;
    }

    @Override
    public E poll() {
        if (isEmpty()) {
            return null;
        }
        int idx = head & array.length - 1;
        E value = array[idx];
        array[idx] = null; // help GC
        head++;
        return value;
    }

    @Override
    public E peek() {
        if (isEmpty()) {
            return null;
        }
        return array[head & array.length - 1];
    }

    @Override
    public boolean isEmpty() {
        return head == tail;
    }

    @Override
    public boolean isFull() {
        return tail - head == array.length;
    }

    @Override
    public Iterator<E> iterator() {
        return new Iterator<E>() {
            int index = head;

            @Override
            public boolean hasNext() {
                return index != tail;
            }

            @Override
            public E next() {
                E value = array[index & array.length - 1];
                index++;
                return value;
            }
        };
    }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2224087.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java如何实现PDF转高质量图片

大家好&#xff0c;我是 V 哥。在Java中&#xff0c;将PDF文件转换为高质量的图片可以使用不同的库&#xff0c;其中最常用的库之一是 Apache PDFBox。通过该库&#xff0c;你可以读取PDF文件&#xff0c;并将每一页转换为图像文件。为了提高图像的质量&#xff0c;你可以指定分…

卷积神经网络评价指标

1.评价指标的作用 1. 性能评估&#xff1a;评价指标提供了一种量化的方式来衡量CNN模型的性能。通过这些指标&#xff0c;我们可以了解模型在特定任务上的表现&#xff0c;比如图像分类、目标检测或图像分割等。 2. 模型比较&#xff1a;不同的模型架构或训练策略可能会产生不…

Pytest-Bdd-Playwright 系列教程(2):支持在多浏览器、多环境中执行测试

Pytest-Bdd-Playwright 系列教程&#xff08;2&#xff09;&#xff1a;支持在多浏览器、多环境中执行测试 前言一、 修改 conftest.py 文件二、创建配置文件三、修改search_steps.py文件四、运行测试 前言 学会本文教程内容后&#xff0c;你将掌握&#xff1a; 通过本文的学…

重构案例:将纯HTML/JS项目迁移到Webpack

我们已经了解了许多关于 Webpack 的知识&#xff0c;但要完全熟练掌握它并非易事。一个很好的学习方法是通过实际项目练习。当我们对 Webpack 的配置有了足够的理解后&#xff0c;就可以尝试重构一些项目。本次我选择了一个纯HTML/JS的PC项目进行重构&#xff0c;项目位于 GitH…

深度学习案例:带有一个隐藏层的平面数据分类

该案例来自吴恩达深度学习系列课程一《神经网络和深度学习》第三周编程作业&#xff0c;作业内容是设计带有一个隐藏层的平面数据分类。作业提供的资料包括测试实例&#xff08;testCases.py&#xff09;和任务功能包&#xff08;planar_utils.py&#xff09;&#xff0c;下载请…

Jetpack架构组件_LiveData组件

1.LiveData初识 LiveData:ViewModel管理要展示的数据&#xff08;VM层类似于原MVP中的P层&#xff09;&#xff0c;处理业务逻辑&#xff0c;比如调用服务器的登陆接口业务。通过LiveData观察者模式&#xff0c;只要数据的值发生了改变&#xff0c;就会自动通知VIEW层&#xf…

Flutter TextField和Button组件开发登录页面案例

In this section, we’ll go through building a basic login screen using the Button and TextField widgets. We’ll follow a step-bystep approach, allowing you to code along and understand each part of the process. Let’s get started! 在本节中&#xff0c;我们…

【Python爬虫系列】_031.Scrapy_模拟登陆中间件

课 程 推 荐我 的 个 人 主 页:👉👉 失心疯的个人主页 👈👈入 门 教 程 推 荐 :👉👉 Python零基础入门教程合集 👈👈虚 拟 环 境 搭 建 :👉👉 Python项目虚拟环境(超详细讲解) 👈👈PyQt5 系 列 教 程:👉👉 Python GUI(PyQt5)教程合集 👈👈…

ArcGIS001:ArcGIS10.2安装教程

摘要&#xff1a;本文详细介绍arcgis10.2的安装、破解、汉化过程。 一、软件下载 安装包链接&#xff1a;https://pan.baidu.com/s/1T3UJ7t_ELZ73TH2wGOcfpg?pwd08zk 提取码&#xff1a;08zk 二、安装NET Framework 3.5 双击打开控制面板&#xff0c;点击【卸载程序】&…

World of Warcraft [CLASSIC][80][the Ulduar]

Ulduar 奥杜尔副本介绍 奥杜尔共计14个BOSS&#xff0c;通常说的10H就是10个苦难模式就是全通&#xff0c;9H就是除了【观察者奥尔加隆】&#xff0c;特别说明开启【观察者奥尔加隆】&#xff0c;是需要打掉困难模式4个守护者的。 所以人们经常说的类似“10H 观察者”、“10H…

Python开发日记 -- 实现bin文件的签名

目录 1.数据的不同表现形式签名值不一样&#xff1f; 2.Binascii模块简介 3.问题定位 4.问题总结 1.数据的不同表现形式签名值不一样&#xff1f; Happy Muscle试运行了一段时间&#xff0c;组内同事再一次提出了新的需求&#xff1a;需要对bin文件签名。 PS&#xff1a;服…

react18中的函数组件底层渲染原理分析

react 中的函数组件底层渲染原理 react组件没有局部与全局之分&#xff0c;它是一个整体。这点跟vue的组件化是不同的。要实现 react 中的全局组件&#xff0c;可以将组件挂在react上&#xff0c;这样只要引入了react&#xff0c;就可以直接使用该组件。 函数式组件的创建 …

Kafka之消费者客户端

1、历史上的二个版本 与生产者客户端一样&#xff0c;在Kafka的发展过程当中&#xff0c;消费者客户端主要有两个大的版本&#xff1a; 旧消费者客户端&#xff08;Old Consumer&#xff09;&#xff1a;基于Scala语言开发的版本&#xff0c;又称为Scala消费者客户端。新消费…

【力扣】GO解决子序列相关问题

文章目录 一、引言二、动态规划方法论深度提炼子序列问题的通用解法模式 三、通用方法论应用示例&#xff1a;最长递增子序列&#xff08;LeetCode题目300&#xff09;Go 语言代码实现 四、最长连续递增序列&#xff08;LeetCode题目674&#xff09;Go 语言代码实现 五、最长重…

ffmpeg视频滤镜:定向模糊-dblur

滤镜简述 dblur 官网链接 > https://ffmpeg.org/ffmpeg-filters.html#dblur 有一个模糊滤镜&#xff0c;我试了一下&#xff0c;没有感觉到它的特殊之处, 这里简单介绍一下。 滤镜使用 滤镜的参数 angle <float> ..FV.....T. set angle (from 0 t…

找不到包的老版本???scikit-learn,numpy,scipy等等!!

废话不多说 直接上链接了&#xff1a; https://pypi.tuna.tsinghua.edu.cn/simple/https://pypi.tuna.tsinghua.edu.cn/simple/https://pypi.tuna.tsinghua.edu.cn/simple/xxx/ 后面的这个xxx就是包的名字 大家需要什么包的版本&#xff0c;直接输进去就可以啦 举个栗子&#…

零基础Java第十期:类和对象(一)

目录 一、拜访对象村 1.1. 什么是面向对象 1.2. 面向对象与面向过程 二、类定义和使用 2.1. 类的定义格式 2.2. 类的定义练习 三、类的实例化 3.1. 什么是实例化 3.2. 类和对象的说明 四、this引用 4.1. 什么是this引用 4.2. this引用的特性 一、拜访对象村 在…

<项目代码>YOLOv8路面病害识别<目标检测>

YOLOv8是一种单阶段&#xff08;one-stage&#xff09;检测算法&#xff0c;它将目标检测问题转化为一个回归问题&#xff0c;能够在一次前向传播过程中同时完成目标的分类和定位任务。相较于两阶段检测算法&#xff08;如Faster R-CNN&#xff09;&#xff0c;YOLOv8具有更高的…

STMicroelectronics意法半导体车规芯片系列--亿配芯城(ICgoodFind)

在汽车电子领域&#xff0c;意法半导体的车规级芯片系列一直备受瞩目。亿配芯城作为电子元器件领域的可靠供应商&#xff0c;为大家介绍意法半导体车规级芯片系列的卓越之处。 意法半导体在车规级芯片领域拥有深厚的技术积累和丰富的经验。 其车规级芯片涵盖了多个关键领域&am…

8.three.js相机详解

8.three.js相机详解 1、 认识相机 在Threejs中相机的表示是THREE.Camera&#xff0c;它是相机的抽象基类&#xff0c;其子类有两种相机&#xff0c;分别是正投影相机THREE.OrthographicCamera和透视投影相机THREE.PerspectiveCamera&#xff1a; 正投影和透视投影的区别是&am…