数据结构第08小节:双端队列

双端队列(deque,double-ended queue)是一种具有队列和栈特性的数据结构,允许在其两端进行插入和删除操作。在Java中,java.util.Deque接口就是双端队列的实现,而ArrayDequeLinkedList是其中的具体实现类。

下面是一个使用ArrayDeque实现的双端队列的例子,我们将使用它来管理一个在线购物车系统中的商品列表。用户可以从任何一端(前面或后面)添加或移除商品。

import java.util.ArrayDeque;
import java.util.Deque;// 商品类
class Product {String name;double price;public Product(String name, double price) {this.name = name;this.price = price;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", price=" + price +'}';}
}public class ShoppingCart {private Deque<Product> cart;public ShoppingCart() {cart = new ArrayDeque<>();}// 向购物车尾部添加商品public void addProduct(Product product) {cart.addLast(product);}// 向购物车头部添加商品public void addFirstProduct(Product product) {cart.addFirst(product);}// 从购物车尾部移除商品public Product removeProduct() {return cart.pollLast();}// 从购物车头部移除商品public Product removeFirstProduct() {return cart.pollFirst();}// 显示购物车中的所有商品public void displayCart() {while (!cart.isEmpty()) {System.out.println(cart.pollFirst());}}public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();// 添加商品cart.addProduct(new Product("Apple iPhone 13", 999.99));cart.addFirstProduct(new Product("Google Pixel 6", 599.99));cart.addProduct(new Product("Samsung Galaxy S21", 799.99));// 显示购物车内容System.out.println("Shopping Cart Contents:");cart.displayCart();// 移除商品System.out.println("\nAfter removing the last item:");cart.removeProduct();cart.displayCart();// 再次移除商品System.out.println("\nAfter removing the first item:");cart.removeFirstProduct();cart.displayCart();}
}

在这个例子中:

  • Product 类表示商品,包含名称和价格属性。
  • ShoppingCart 类使用ArrayDeque作为内部数据结构来存储商品。它提供了添加商品到队列尾部或头部的方法,以及从队列尾部或头部移除商品的方法。
  • main 方法创建了一个ShoppingCart对象,添加了一些商品,显示了购物车的内容,然后移除了商品并再次显示购物车的内容。

这个例子展示了如何使用Java中的双端队列来管理一个购物车系统中的商品列表,允许用户从任意一端添加或移除商品,这在许多实际应用场景中都非常有用。

让我们通过一个详细的案例和表格来进一步说明如何使用双端队列(Deque)在Java中管理一个购物车系统。我们将使用ArrayDeque作为我们的双端队列实现,并跟踪购物车中的商品添加和移除操作。

示例代码

import java.util.ArrayDeque;
import java.util.Deque;// 商品类
class Product {String name;double price;public Product(String name, double price) {this.name = name;this.price = price;}@Overridepublic String toString() {return "Product{" +"name='" + name + '\'' +", price=" + price +'}';}
}public class ShoppingCart {private Deque<Product> cart;public ShoppingCart() {cart = new ArrayDeque<>();}// 向购物车尾部添加商品public void addProduct(Product product) {cart.addLast(product);}// 向购物车头部添加商品public void addFirstProduct(Product product) {cart.addFirst(product);}// 从购物车尾部移除商品public Product removeProduct() {return cart.pollLast();}// 从购物车头部移除商品public Product removeFirstProduct() {return cart.pollFirst();}// 显示购物车中的所有商品public void displayCart() {System.out.println("Current Cart Contents:");for (Product product : cart) {System.out.println(product);}}public static void main(String[] args) {ShoppingCart cart = new ShoppingCart();// 添加商品到购物车cart.addProduct(new Product("Apple iPhone 13", 999.99));cart.addFirstProduct(new Product("Google Pixel 6", 599.99));cart.addProduct(new Product("Samsung Galaxy S21", 799.99));// 显示购物车内容cart.displayCart();// 移除商品System.out.println("\nAfter removing the last item:");cart.removeProduct();cart.displayCart();// 再次移除商品System.out.println("\nAfter removing the first item:");cart.removeFirstProduct();cart.displayCart();}
}

表格说明

购物车操作记录
操作描述购物车状态(从左至右为队首至队尾)
初始化创建一个空的购物车[]
添加到队尾(addLast)添加“Apple iPhone 13”[“Apple iPhone 13”]
添加到队首(addFirst)添加“Google Pixel 6”[“Google Pixel 6”, “Apple iPhone 13”]
添加到队尾(addLast)添加“Samsung Galaxy S21”[“Google Pixel 6”, “Apple iPhone 13”, “Samsung Galaxy S21”]
移除队尾(removeLast)移除“Samsung Galaxy S21”[“Google Pixel 6”, “Apple iPhone 13”]
移除队首(removeFirst)移除“Google Pixel 6”[“Apple iPhone 13”]

通过这个案例和表格,我们可以清楚地看到双端队列在购物车管理中的应用:商品可以被添加到队列的任一端,也可以从任一端移除。这种灵活性使得双端队列成为处理双向数据流或需要快速访问两端数据的场景的理想选择。

让我们继续深入探讨双端队列(Deque)的应用,这一次我们将使用它来解决一个常见的编程问题:回文检测。回文是指正读反读都一样的字符串,例如“racecar”。我们将使用双端队列的特性来高效地检查一个给定的字符串是否是回文。

示例代码

import java.util.ArrayDeque;
import java.util.Deque;public class PalindromeChecker {public static boolean isPalindrome(String str) {Deque<Character> deque = new ArrayDeque<>();// 将字符串中的字符添加到双端队列中for (char c : str.toLowerCase().toCharArray()) {if (Character.isLetter(c)) {deque.addLast(c);}}char first, last;while (deque.size() > 1) {first = deque.removeFirst();last = deque.removeLast();if (first != last) {return false;}}return true;}public static void main(String[] args) {String testString = "A man a plan a canal Panama";if (isPalindrome(testString)) {System.out.println(testString + " is a palindrome.");} else {System.out.println(testString + " is not a palindrome.");}}
}

代码解释

在这段代码中,我们定义了一个名为PalindromeChecker的类,其中包含一个静态方法isPalindrome,该方法接受一个字符串参数并返回一个布尔值,指示该字符串是否为回文。

  1. 初始化双端队列:我们使用ArrayDeque作为双端队列的实现,并将其实例化。
  2. 添加字符:遍历输入字符串的每个字符,只将字母字符转换为小写并添加到队列的尾部。
  3. 比较字符:从双端队列的头部和尾部同时移除字符,并比较它们是否相同。如果任何时候两个字符不匹配,那么字符串就不是回文,方法立即返回false
  4. 结束条件:如果队列中只剩下一个字符或没有字符,则说明字符串是回文,方法返回true

运行结果

当你运行main方法时,它会检查字符串“A man a plan a canal Panama”是否为回文。由于忽略空格和大小写,这个字符串实际上是一个回文,因此控制台将输出:“A man a plan a canal Panama is a palindrome.”

这个例子展示了如何利用双端队列的特性来简化和优化一些算法,如回文检测,这在实际编程中是非常有用的技巧。

接下来,我们将使用双端队列(Deque)来解决一个有趣的问题:浏览器的历史记录管理。当我们浏览网页时,通常会使用浏览器的前进和后退按钮来在历史记录之间导航。双端队列非常适合模拟这一行为,因为它允许我们在队列的两端高效地添加和移除元素。

示例代码

import java.util.ArrayDeque;
import java.util.Deque;public class BrowserHistory {private Deque<String> history;private Deque<String> forwardHistory;public BrowserHistory() {history = new ArrayDeque<>();forwardHistory = new ArrayDeque<>();}// 访问新的网址public void visit(String url) {history.addLast(url);forwardHistory.clear(); // 清空前进历史}// 返回上一个页面public String back() {if (history.size() > 1) {String currentUrl = history.removeLast();forwardHistory.addFirst(currentUrl);return history.getLast();} else {return "No more pages to go back.";}}// 前往下一个页面public String forward() {if (!forwardHistory.isEmpty()) {String nextUrl = forwardHistory.removeFirst();history.addLast(nextUrl);return nextUrl;} else {return "No more pages to go forward.";}}public static void main(String[] args) {BrowserHistory browser = new BrowserHistory();// 访问一些网址browser.visit("google.com");browser.visit("youtube.com");browser.visit("facebook.com");// 后退到上一个页面System.out.println("Back: " + browser.back());// 再次后退System.out.println("Back again: " + browser.back());// 前进到下一个页面System.out.println("Forward: " + browser.forward());}
}

表格说明

浏览器历史记录操作记录
操作描述当前页面历史记录(从左至右为最新至最旧)前进历史(从左至右为最近至最远)
初始化创建一个新的浏览器历史管理器N/A[][]
访问(visit)访问“google.com”google.com[“google.com”][]
访问(visit)访问“youtube.com”youtube.com[“google.com”, “youtube.com”][]
访问(visit)访问“facebook.com”facebook.com[“google.com”, “youtube.com”, “facebook.com”][]
后退(back)后退到上一个页面youtube.com[“google.com”, “youtube.com”][“facebook.com”]
后退(back)再次后退google.com[“google.com”][“youtube.com”, “facebook.com”]
前进(forward)前进到下一个页面youtube.com[“google.com”, “youtube.com”][“facebook.com”]

通过这个案例和表格,我们可以看到双端队列如何有效地模拟浏览器的历史记录管理。每当访问一个新的网址时,它会被添加到历史记录的尾部,并清空前进历史。后退操作会从历史记录的尾部移除当前页面并将其添加到前进历史的头部,而前进操作则相反。这种方法保证了高效且直观的网页导航体验。

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

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

相关文章

如何根据经纬度精确计算两点之间的距离

以下代码用python2运行 #!/usr/bin/python #codingutf-8 from __future__ import print_function import sys reload(sys) sys.setdefaultencoding("utf-8") import mathdef haversine_distance(lon1, lat1, lon2, lat2):# 将纬度和经度从度转换为弧度lat1_rad mat…

【C#】函数方法、属性分文件编写

1.思想 分文件编写是面向对象编程的重要思想&#xff0c;没有实际项目作为支撑很难理解该思想的精髓&#xff0c;换言之&#xff0c;一两个函数代码量因为太少无法体现分文件编写减少大量重复代码的优势。 2.项目结构介绍 整项目的名称叫AutoMetadata&#xff0c;是一个基于W…

JAVA:文件防重设计指南

1、简述 在现代应用程序中&#xff0c;处理文件上传是一个常见的需求。为了保证文件存储的高效性和一致性&#xff0c;避免重复存储相同的文件是一个重要的优化点。本文将介绍一种基于哈希值的文件防重设计&#xff0c;并详细列出实现步骤。 2、设计原理 文件防重的基本思路…

Dns被莫名篡改的逆向分析定位(笔记)

引言&#xff1a;最近发现用户的多台机器上出现了Dns被莫名修改的问题&#xff0c;从系统事件上看并未能正常确定到是那个具体软件所为&#xff0c;现在的需求就是确定和定位哪个软件具体所为。 解决思路&#xff1a; 首先到IPv4设置页面对Dns进行设置&#xff1a;通过ProcExp…

setjmp和longjmp函数使用

这里用最简单直接的描述&#xff1a;这两组函数是用于实现类似vscode全局的标签跳转功能&#xff0c;setjmp负责埋下标签&#xff0c;longjmp负责标签跳转。 #include <stdio.h> #include <stdlib.h> #include <setjmp.h>jmp_buf envbuf1; jmp_buf envbuf2;…

HttpServer内存马

HttpServer内存马 基础知识 一些基础的方法和类 HttpServer&#xff1a;HttpServer主要是通过带参的create方法来创建&#xff0c;第一个参数InetSocketAddress表示绑定的ip地址和端口号。第二个参数为int类型&#xff0c;表示允许排队的最大TCP连接数&#xff0c;如果该值小…

【面试系列】软件工程师高频面试题及详细解答

欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;欢迎订阅相关专栏&#xff1a; ⭐️ 全网最全IT互联网公司面试宝典&#xff1a;收集整理全网各大IT互联网公司技术、项目、HR面试真题. ⭐️ AIGC时代的创新与未来&#xff1a;详细讲解AIGC的概念、核心技术、…

JAVA每日作业day7.4

ok了家人们今天学习了Date类和simpleDateformat类&#xff0c;话不多说我们一起看看吧 一.Date类 类 java.util.Date 表示特定的瞬间 ( 日期和时间 ) &#xff0c;精确到毫秒。 1.2 Date类的构造方法 public Date(): 用来创建当前系统时间对应的日期对象。 public Date(long …

【java开发环境】多版本jdk 自由切换window和linux

win10 一、准备 各种版本的jdk&#xff0c;按自己的需要下载。 我这里是需要jdk17和jdk8。 1、jdk17 下载&#xff1a;Java Downloads | Oracle&#xff0c;选择exe后缀文件 2、jdk8下 载&#xff1a;Java Downloads | Oracle&#xff0c;选择exe后缀文件 二、详细步骤 1、…

Linux线程:编织并发的梦幻世界

目录 &#x1f6a9;引言 &#x1f6a9;听故事&#xff0c;引概念 &#x1f6a9;生产者消费者模型 &#x1f680;再次理解生产消费模型 &#x1f680;挖掘特点 &#x1f6a9;条件变量 &#x1f680;条件变量常用接口 &#x1f680;条件变量的原理 &#x1f6a9;引言 上一篇…

Redis分布式锁代码实现详解

引言 在分布式系统中&#xff0c;资源竞争和数据一致性问题常常需要通过锁机制来解决。Redis作为一个高性能的键值存储系统&#xff0c;因其提供的原子操作、丰富的数据结构以及网络延迟低等特点&#xff0c;成为了实现分布式锁的理想选择。本文将详细介绍如何使用Redis来实现…

打卡第2天----数组双指针,滑动窗口

今天是参与训练营第二天&#xff0c;这几道题我都看懂了&#xff0c;自己也能写出来了&#xff0c;实现思路很重要&#xff0c;万事开头难&#xff0c;希望我可以坚持下去。希望最后的结果是量变带来质变。 一、理解双指针思想 leetcode编号&#xff1a;977 不止是在卡尔这里…

一篇文章说清楚Filter(过滤器)、Interceptor(拦截器)和AOP(切面儿)

文章目录 前言一、Filter&#xff08;过滤器&#xff09;1.说明2.实现filterChain.doFilter() 3.order优先级4.解决跨域5.拦截返回错误信息JSON 二、Interceptor&#xff08;拦截器&#xff09;1.说明2.实现preHandlepostHandleafterCompletion 3.执行顺序图4.排除特定路径拦截…

【LinuxC语言】线程退出函数的实现

文章目录 前言线程退出函数的作用和实现流程函数实现线程池代码概况总结前言 在并发编程中,线程的创建和销毁是两个非常重要的环节。在Linux C语言环境下,我们可以使用POSIX线程库(pthread)来创建和控制线程。然而,线程的退出并不是一个简单的过程,它涉及到许多细节,如…

论文学习——基于类型检测的动态自适应多目标优化算法

论文题目&#xff1a;Dynamic adaptive multi-objective optimization algorithm based on type detection 基于类型检测的动态自适应多目标优化算法&#xff08;Xingjuan Cai a,b, Linjie Wu a,∗, Tianhao Zhao a, Di Wu c, Wensheng Zhang d, Jinjun Chen e&#xff09;Inf…

yum命令提示 错误:rpmdb: BDB0113 Thread/process 4153/139708200269632

一、报错信息 [rootDawn yum.repos.d]# yum clean all 错误&#xff1a;rpmdb: BDB0113 Thread/process 4153/139708200269632 failed: BDB1507 Thread died in Berkeley DB library 错误&#xff1a;db5 错误(-30973) 来自 dbenv->failchk&#xff1a;BDB0087 DB_RUNRECOVE…

HTTP与HTTPS协议区别及应用场景

HTTP&#xff08;超文本传输​​协议&#xff09;和 HTTPS&#xff08;安全超文本传输​​协议&#xff09;都是用于通过网络传输数据的协议。虽然它们有一些相似之处&#xff0c;但在安全性和数据保护方面也存在显著差异。 在这篇博文中&#xff0c;我们将探讨 HTTP 和 HTTPS…

websocket的工作原理

WebSocket 是一种在 Web 应用程序中实现全双工通信的协议。它允许客户端和服务器之间建立一个持久的连接&#xff0c;双方可以在这个连接上相互发送数据&#xff0c;而不需要通过传统的 HTTP 请求/响应模式。这使得 WebSocket 特别适用于实时应用&#xff0c;如聊天应用、在线游…

pytorch中的contiguous()

官方文档&#xff1a;https://pytorch.org/docs/stable/generated/torch.Tensor.contiguous.html 其描述contiguous为&#xff1a; Returns a contiguous in memory tensor containing the same data as self tensor. If self tensor is already in the specified memory forma…

自然语言处理与Transformer模型:革新语言理解的新时代

引言 自然语言处理&#xff08;NLP&#xff09;是人工智能和计算机科学的一个重要分支&#xff0c;旨在使计算机能够理解、生成和处理人类语言。随着互联网和数字化信息的爆炸性增长&#xff0c;NLP在许多领域中的应用变得越来越重要&#xff0c;包括&#xff1a; 搜索引擎&am…