数据结构与算法——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 从手动编写到标准化解决方…

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; // 将新…

在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 --…

《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仿函数的介绍…

【C语言】指针篇 | 万字笔记

写在前面 在学习C语言过程&#xff0c;总有一个要点难点离不开&#xff0c;那就是大名鼎鼎的C语言指针&#xff0c;也是应为有指针的存在&#xff0c;使得C语言一直长盛不衰。因此不才把指针所学的所有功力都转换成这个笔记。希望对您有帮助&#x1f970;&#x1f970; 学习指…

彩虹易支付最新版源码及安装教程(修复BUG+新增加订单投诉功能)

该系统也没版本号&#xff0c;此版本目前是比较新的版本&#xff0c;增加了订单投诉功能&#xff0c;和一个好看的二次元模板。 此版本是全开源版&#xff0c;无一处加密文件,系统默认是安装后是打不开的&#xff0c; 本站特别修复了BUG文件&#xff0c;在PHP7.4环境下也没问…

Java的学习(语法相关)

字符串存储的问题 char 和字符串都是字符的集合&#xff0c;它们之间的确有相似性&#xff0c;但在 Java 中它们有着不同的存储机制和处理方式。让我从 char 和 String 的本质区别入手来解释。 1. char 和 String 的区别 char 是基本类型&#xff1a;char 是 Java 中的基本数据…

【C++】多态(下)

个人主页~ 多态&#xff08;上&#xff09;~ 多态 四、多态的原理1、虚表的存储位置2、多态的原理3、动态绑定和静态绑定 五、单继承和多继承关系的虚函数表1、单继承中的虚函数表2、多继承中的虚函数表 六、多态中的一些小tips 四、多态的原理 1、虚表的存储位置 class A {…

CORE MVC 过滤器 (筛选器)

MVC FrameWork MVCFramework MVC Core 过滤器 分 同步、异步 1、 授权筛选器 IAuthorizationFilter&#xff0c;IAsyncAuthorizationFilter 管道中运行的第一类筛选器&#xff0c;用来确定发出请求的用户是否有权限发出当前请求 2、资源筛选器 IResourceFilter &#xff0c;…

微软准备了 Windows 11 24H2 ISO “OOBE/BypassNRO“命令依然可用

Windows 11 24H2 可能在未来几周内开始推出。 微软已经要求 OEM 遵循新的指南准备好 Windows 11 24H2 就绪的驱动程序&#xff0c;并且现在已经开始准备媒体文件 (.ISO)。 OEM ISO 的链接已在微软服务器上发布。 一个标有"X23-81971_26100.1742.240906-0331.ge_release_sv…

Vue3项目开发——新闻发布管理系统(九)(完结篇)

文章目录 十一、用户信息管理1、用户基本资料管理1.1 页面设计1.2 封装接口,更新信息2、更换头像2.1 静态结构2.2 选择图片预览2.3 上传头像3、重置密码3.1 页面设计3.2 封装接口,更新密码十二、项目打包十三、系统全部源码下载十一、用户信息管理 用户信息管理包括功能:基…

第四届机器人、自动化与智能控制国际会议(ICRAIC 2024)征稿

第四届机器人、自动化与智能控制国际会议&#xff08;ICRAIC 2024&#xff09;由湖南第一师范学院主办&#xff0c;南京师范大学、山东女子学院、爱迩思出版社&#xff08;ELSP&#xff09;协办。 大会将专注于机器人、数字化、自动化、人工智能等技术的开发和融合&#xff0c…

如何让 Android 的前端页面像 iOS 一样“优雅”?

作者:方英杰&#xff08;崇之&#xff09; 最近在调研前端页面适配 Android 端异形屏的方案&#xff0c;调研过程中发现了一些比较有意思的点&#xff0c;本文主要是做一个总结。 一、提出问题 首先&#xff0c;我们需要知道 Android 上的前端适配面临着什么问题。 问题其实很…

【含文档】基于Springboot+Vue的停车场车位预约系统(含源码+数据库+lw)

1.开发环境 开发系统:Windows10/11 架构模式:MVC/前后端分离 JDK版本: Java JDK1.8 开发工具:IDEA 数据库版本: mysql5.7或8.0 数据库可视化工具: navicat 服务器: SpringBoot自带 apache tomcat 主要技术: Java,Springboot,mybatis,mysql,vue 2.视频演示地址 3.功能 系统定…