数据结构与算法——Java实现 27.双端队列

很多人觉得做一件事付出了10分的努力,却只得到5分的汇报。

其实剩下的五分,是在填补你过往的懒惰。

只有将过往的懒惰填满,

努力才会有正向结果

                                                                                        —— 24.10.3

一、概述

双端队列、队列、栈对比:

队列

        一端删除(头),一段添加(尾)        先进先出(FIFO)

        一端删除和添加        后进先出(LIFO)

双端队列

        队列的两端都可以添加、删除


二、双端队列——双向环形链表实现

双端队列要求队头队尾都可以添加和删除元素

所以为了使所有节点都方便计算,于是添加两个指针prevnext,一个指向每个节点的前一个元素,另一个指向一个每个节点的后一个元素,这样在队列头尾删除或添加元素时,只需要通过节点前后节点的指向,快捷删除

定义哨兵节点sentinel,根据哨兵节点前后指针的指向,进行添加和删除

接口

public interface Deque<E> {/*向队列头部添加元素Returns:bool类型,添加是否成功*/boolean offerFirst(E e);/*向队列尾部添加元素Returns:bool类型,添加是否成功*/boolean offerLast(E e);/*从队列的头部删除元素Returns:返回删除的元素*/E pollFirst();/*从队列的尾部删除元素Returns:返回删除的元素*/E pollLast();/*从队列的头部获取元素Returns:获取头部的元素*/E peekFirst();/*从队列的尾部获取元素Returns:获取尾部的元素*/E peekLast();/*判断队列是否为空Returns:判断是否为空*/boolean isEmpty();/*判断队列是否为满Returns:判断是否为满*/boolean isFull();
}

环形链表类

import java.util.Iterator;/*基于双向环形链表实现双端队列Type parameters <E> —— 队列中元素类型*/
public class LinkedListDeque<E> implements Deque<E>,Iterable<E>{// 容量int capacity;// 元素个数int size;// 哨兵Node<E> sentinel = new Node<>(null, null, null);// 首部添加@Overridepublic boolean offerFirst(E e) {if (isFull()) {return false;}Node<E> a = sentinel;Node<E> b = sentinel.next;// 新添加的节点Node<E> added = new Node<>(a,e,b);a.next = added;b.prev = added;size++;return true;}// 尾部添加@Overridepublic boolean offerLast(E e) {if (isFull()) {return false;}Node<E> a = sentinel.prev;Node<E> b = sentinel;Node<E> added = new Node<>(a,e,b);a.next = added;b.prev = added;size++;return true;}// 头部删除@Overridepublic E pollFirst() {if (isEmpty()){return null;}Node<E> a = sentinel;Node<E> remove = sentinel.next;Node<E> b = sentinel.next.next;a.next = b;b.prev = a;size--;return remove.value;}// 尾部删除@Overridepublic E pollLast() {if(isEmpty()){return null;}Node<E> a = sentinel;Node<E> remove = sentinel.prev;Node<E> b = sentinel.prev.prev;b.next = a;a.prev = b;size--;return remove.value;}// 首部获取@Overridepublic E peekFirst() {if (isEmpty()) {return null;}Node<E> node = sentinel.next;return node.value;}// 尾部获取@Overridepublic E peekLast() {if (isEmpty()) {return null;}Node<E> node = sentinel.prev;return node.value;}// 判空@Overridepublic boolean isEmpty() {return size==0;}// 判满@Overridepublic boolean isFull() {return size==capacity;}// 迭代器@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {Node<E> p = sentinel.next;@Overridepublic boolean hasNext() {return p!=sentinel;}@Overridepublic E next() {E value = p.value;p = p.next;return value;}};}// 节点类 prev指针指向上一个节点,next指针指向下一个节点static class Node<E> {Node<E> prev;E value;Node<E> next;public Node(Node<E> prev, E value, Node<E> next) {this.prev = prev;this.value = value;this.next = next;}}public LinkedListDeque(int capacity) {this.capacity = capacity;sentinel.next = sentinel;sentinel.prev = sentinel;}
}

 测试类

import static org.junit.jupiter.api.Assertions.*;
import org.junit.Test;import java.util.List;public class TestLinkedListDeque {// 添加节点@Testpublic void offer(){LinkedListDeque<Integer> deque = new LinkedListDeque<>(5);deque.offerFirst(3);deque.offerLast(4);deque.offerFirst(2);deque.offerLast(5);deque.offerFirst(1);assertFalse(deque.offerLast(6));assertIterableEquals(List.of(1,2,3,4,5),deque);}// 移除节点@Testpublic void poll(){LinkedListDeque<Integer> deque = new LinkedListDeque<>(5);deque.offerFirst(3);deque.offerLast(4);deque.offerFirst(2);deque.offerLast(5);deque.offerFirst(1);assertEquals(1, deque.pollFirst());assertEquals(2, deque.pollFirst());assertEquals(3, deque.pollFirst());assertEquals(4, deque.pollFirst());assertEquals(5, deque.pollLast());assertNull(deque.pollLast());assertTrue(deque.isEmpty());}}


三、双端队列——数组实现

基于循环数组实现

head:头指针        tail:尾指针

特点:tail停下来的位置不存储,会浪费一个位置

Type parameters:<E>——队列中元素类型

 接口

public interface Deque<E> {/*向队列头部添加元素Returns:bool类型,添加是否成功*/boolean offerFirst(E e);/*向队列尾部添加元素Returns:bool类型,添加是否成功*/boolean offerLast(E e);/*从队列的头部删除元素Returns:返回删除的元素*/E pollFirst();/*从队列的尾部删除元素Returns:返回删除的元素*/E pollLast();/*从队列的头部获取元素Returns:获取头部的元素*/E peekFirst();/*从队列的尾部获取元素Returns:获取尾部的元素*/E peekLast();/*判断队列是否为空Returns:判断是否为空*/boolean isEmpty();/*判断队列是否为满Returns:判断是否为满*/boolean isFull();
}

循环数组类

import java.util.Iterator;public class ArrayDeque<E> implements Deque<E>,Iterable<E> {// 两个工具方法 1static int inc(int i,int length){if (i + 1 >= length){return 0;}return i + 1;}// 两个工具方法 2static int dec(int i,int length){if (i - 1 < 0){return length - 1;}return i - 1;}E[] array;int head;int tail;@SuppressWarnings("all")public ArrayDeque(int capacity){array = (E[]) new Object[capacity+1];}@Overridepublic boolean offerFirst(E e) {if (isFull()){return false;}head = dec(head, array.length);array[head] = e;return true;}@Overridepublic boolean offerLast(E e) {if (isFull()){return false;}array[tail] = e;tail = inc(tail, array.length);return true;}@Overridepublic E pollFirst() {if (isEmpty()){return null;}E e = array[head];// 帮助垃圾回收array[head] = null;head = inc(head,array.length);return e;}@Overridepublic E pollLast() {if (isEmpty()){return null;}tail = dec(tail,array.length);E e = array[tail];// 帮助垃圾回收array[tail] = null;return e;}@Overridepublic E peekFirst() {if (isEmpty()){return null;}return array[head];}@Overridepublic E peekLast() {if (isEmpty()){return null;}return array[dec(tail, array.length)];}@Overridepublic boolean isEmpty() {return head == tail;}@Overridepublic boolean isFull() {if (tail > head){return tail - head == array.length - 1;} else if (tail < head) {return head - tail == 1;} else {return false;}}@Overridepublic Iterator<E> iterator() {return new Iterator<E>() {int p = head;@Overridepublic boolean hasNext() {return p != tail;}@Overridepublic E next() {E e = array[p];p = inc(p,array.length);return e;}};}
}

测试类

import org.junit.Test;import java.util.List;import static org.junit.jupiter.api.Assertions.*;public class TestArrayDeque {@Testpublic void offer() {ArrayDeque<Integer> deque = new ArrayDeque<>(5);deque.offerFirst(1);deque.offerLast(2);deque.offerLast(3);deque.offerLast(4);deque.offerLast(5);assertFalse(deque.offerLast(3));assertIterableEquals(List.of(1,2,3,4,5), deque);}@Testpublic void poll() {ArrayDeque<Integer> deque = new ArrayDeque<>(5);assertTrue(deque.isEmpty());deque.offerFirst(1);deque.offerLast(2);deque.offerLast(3);deque.offerLast(4);deque.offerFirst(5);assertIterableEquals(List.of(5,1,2,3,4),deque);assertTrue(deque.isFull());assertEquals(5, deque.pollFirst());assertEquals(4, deque.pollLast());assertEquals(1 , deque.pollFirst());assertEquals(3 , deque.pollLast());assertEquals(2 , deque.pollFirst());assertNull(deque.pollLast());assertTrue(deque.isEmpty());}
}

垃圾回收机制

因为用泛型实现,所以都是引用类型,我们需要将索引位置的数组值在处理完后赋值为null

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

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

相关文章

C++ STL 初探:打开标准模板库的大门

文章目录 C STL 初探&#xff1a;打开标准模板库的大门前言第一章: 什么是STL&#xff1f;1.1 标准模板库简介1.2 STL的历史背景1.3 STL的组成 第二章: STL的版本与演进2.1 不同的STL版本2.2 STL的影响与重要性 第三章: 为什么学习 STL&#xff1f;3.1 从手动编写到标准化解决方…

探索云计算中的 Serverless 架构:未来的计算范式?

目录 引言 一、Serverless架构概览 二、Serverless 架构的优势 三、Serverless架构的挑战 四、Serverless架构的未来展望 五、结论 引言 在当今快速发展的 IT 行业中&#xff0c;云计算无疑占据了举足轻重的地位。随着技术的不断演进&#xff0c;云计算的一个新兴分支——…

Go语言实现长连接并发框架 - 请求分发器

文章目录 前言接口结构体接口实现项目地址最后 前言 你好&#xff0c;我是醉墨居士&#xff0c;我们上篇博客实现了任务管理器的功能&#xff0c;接下来这篇博客我们将要实现请求分发模块的开发 接口 trait/dispatcher.go type Dispatcher interface {Start()Dispatch(conn…

每日一题学习笔记

统计字符串中的单词个数&#xff0c;这里的单词指的是连续的不是空格的字符。 请注意&#xff0c;你可以假定字符串里不包括任何不可打印的字符。 示例: 输入: "Hello, my name is John" 输出: 5 解释: 这里的单词是指连续的不是空格的字符&#xff0c;所以 "…

Golang | Leetcode Golang题解之第454题四数相加II

题目&#xff1a; 题解&#xff1a; func fourSumCount(a, b, c, d []int) (ans int) {countAB : map[int]int{}for _, v : range a {for _, w : range b {countAB[vw]}}for _, v : range c {for _, w : range d {ans countAB[-v-w]}}return }

骨架屏 (懒加载优化)

骨架屏 &#xff08;懒加载优化&#xff09; 即便通过 Webpack 的按需加载、CDN 静态资源缓存 和 代码分割 等技术来减少首屏的代码体积&#xff0c;首屏加载时的白屏时间&#xff08;也称为首屏等待时间&#xff09;仍然可能存在&#xff0c;尤其在网络条件较差或页面内容复杂…

【前端安全】js逆向之微信公众号登录密码

❤️博客主页&#xff1a; iknow181 &#x1f525;系列专栏&#xff1a; 网络安全、 Python、JavaSE、JavaWeb、CCNP &#x1f389;欢迎大家点赞&#x1f44d;收藏⭐评论✍ 随着发展&#xff0c;越来越多的登录页面添加了密码加密的措施&#xff0c;使得暴力破解变得不在简单&a…

el-table添加fixed后错位问题

1 方案1 return {isShow:false, }mounted() {this.isShowtrue},watch: {$route(newRoute) {this.monitoredRoute newRoute; // 将新的路由信息保存到组件的monitoredRoute属性中// 执行其他操作或调用其他方法},//或$route(newRoute) {this.monitoredRoute newRoute; // 将新…

python三局两胜游戏

分为以下步骤实现这个功能 1、猜拳 2、机器产生数值 3、人去猜数字&#xff0c;定义剪刀石头布 4、控制机器产生&#xff0c;123程序运行的时候可能会出现一点玄学问题&#xff0c;就是&#xff0c;提示n1这一行不符合pep8然后报错&#xff0c;不用管&#xff0c;运行就可以&am…

在Linux系统安装Nginx

注意&#xff1a;Nginx端口号是80(云服务器要放行) 我的是基于yum源安装 安装yum源(下面这4步就好了) YUM源 1、将源文件备份 cd /etc/yum.repos.d/ && mkdir backup && mv *repo backup/ 2、下载阿里源文件 curl -o /etc/yum.repos.d/CentOS-Base.repo ht…

【三步 完全离线搭建 openwebui 】

完全离线linux 版open webui 的搭建 1.在具有网络连接的环境中下载whl 在有网络的环境&#xff0c;使用pip download可以保存所有的依赖包,可以使用-i 指定清华的镜像源加速下载速度。 # 命令&#xff1a; pip download <package_name> --only-binary:all: --wheel --…

VS Code Python 文件导入提示 xxx Module 不存在解决方式

VS Code Python 文件导入提示 xxx Module 不存在解决方式 引言正文如何打开 setting.json 文件引言 之前在 https://blog.csdn.net/u011699626/article/details/142612579?spm=1001.2014.3001.5501 一文中我们介绍了如何配置 VS code 中 Jupyter Notebook 的文件导入环境,这…

接口+内部类

接口和内部类是Java中两个重要的概念&#xff0c;可以在代码中使用它们来实现更灵活和模块化的设计。 接口是一种定义了一组抽象方法的特殊类&#xff0c;其中的方法没有具体的实现。通过实现接口&#xff0c;一个类可以获得接口中定义的方法&#xff0c;并提供实际的实现。接…

使用rust写一个Web服务器——多线程版本

文章目录 模拟慢请求多线程Web服务器实现为每个请求单独生成一个线程限制创建线程的数量ThreadPool的初始化ThreadPool的存储ThreadPool的设计 关闭和资源清理为ThreadPool实现Drop停止工作线程测试 仓库地址&#xff1a; 1037827920/web-server: 使用rust编写的简单web服务器 …

2024年云南省职业院校技能大赛赛程规章(大数据赛项)

大家期待已久的职业院校技能大赛在各个省份已经陆续出新文件了&#xff0c;近日云南省的赛程规章也是出来了&#xff0c;我相信不仅是对云南&#xff0c;对其他省份也很有参考价值&#xff0c;小编为大家精简整理了一下文件的内容。 一、竞赛目标 为适应大数据产业对高素质技术…

【Spring Security】基于SpringBoot3.3.4版本②如何配置免鉴权Path

基于Spring Boot 3.3.4,详细说明Spring Security 6.3.3的使用 摘要本地开发环境说明SecurityFilterChain介绍application.ymlWen3SecurityProperties.java修改DemoWen3Security修改SecurityFilterChainIgnoredPathController.javaIgnoredPathController2.java启动工程测试测试…

《OpenCV 计算机视觉》—— Harris角点检测、SIFT特征检测

文章目录 一、Harris 角点检测1.基本思想2.检测步骤3.OpenCV实现 二、SIFT特征检测1. SIFT特征检测的基本原理2. SIFT特征检测的特点3. OpenCV 实现 一、Harris 角点检测 OpenCV中的Harris角点检测是一种基于图像灰度值变化的角点提取算法&#xff0c;它通过计算每个像素点的响…

[Unity Demo]从零开始制作空洞骑士Hollow Knight第十二集:制作完整地图和地图细节设置以及制作相机系统的跟随玩家和视角锁定功能

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、制作完整的地图和地图细节设置 1.制作地图前的设置2.制作地图前期该做的事3.制作地图之堆叠素材4.制作地图后期该做的事5.制作地图之修复意想不到的Bug二、…

C++仿函数的介绍以及priority_queue的介绍和模拟实现

目录 1.仿函数 1.1仿函数的介绍 1.2自定义类型使用仿函数 1.3自定义支持比较大小&#xff0c;但是比较的逻辑不是自己想要的逻辑 2.优先级队列priority_queue 2.1priority_queue的介绍 2.2priority_queue的使用 2.3priority_queue的模拟实现 1.仿函数 1.1仿函数的介绍…

微信小程序实战教程:如何使用map组件实现地图功能

在微信小程序中&#xff0c;map组件是一个非常实用的功能&#xff0c;它可以帮助我们快速实现地图展示、定位、标注等操作。本文将详细介绍如何在微信小程序中使用map组件&#xff0c;带你轻松掌握地图开发技能。 一、map组件概述 map组件是微信小程序官方提供的一个地图组件…