数据结构——Java实现栈和队列
一、栈 Stack
1.特点
(1)栈是一种线性数据结构
(2)规定只能从栈顶添加元素,从栈顶取出元素
(3)是一种先进后出的数据结构(Last First Out)LIFO
2.具体实现
Java中可以直接调用方法来实现栈

如何自己写代码来实现栈呢?
先定义一个接口,方便后边进行调用
package com.algo.lesson.lesson02.stack;public interface Stack_I<T> {//入栈void push(T ele);//出栈T pop();//查看栈顶元素T peek();//判断是否为空boolean isEmpty();//后去栈中元素int getSize();
}
接下来来实现栈的方法,调用接口,完善方法:
package com.algo.lesson.lesson02.stack;import com.algo.lesson.lesson01.MyArr;//以数组作为栈顶的底层数据结构
public class ArrStack<T> implements Stack_I<T> {private MyArr<T>data;int size;public ArrStack() {this.data=new MyArr<>(100);this.size=0;}@Overridepublic void push(T ele) {//在数组尾部添加元素this.data.add(ele);this.size++;}@Overridepublic T pop() {if(isEmpty()){return null;}this.size--;return this.data.removeBFromLast();}@Overridepublic T peek() {return this.data.getLastValue();}@Overridepublic boolean isEmpty() {return this.size==0;}@Overridepublic int getSize() {return this.size;}
}
以上就是方法的代码,接下来,写个main函数来调用,检查方法是否正确
package com.algo.lesson.lesson02.stack;import java.util.ArrayList;
import java.util.List;
import java.util.Random;public class StackTest<T> {public void test(Stack_I<T>stack, List<T> list){//开始时间long startTime=System.nanoTime();for(int i=0;i<list.size();i++){stack.push(list.get(i));}System.out.println(stack.getSize());while(!stack.isEmpty()){T ele=stack.pop();System.out.println(ele+" ");}//结束时间long endTime=System.nanoTime();System.out.println("总耗时:"+(endTime-startTime)/100000000.0);}public static void main(String[] args) {StackTest<Integer>stackTest=new StackTest<>();Stack_I<Integer>stack=new ArrStack<>();List<Integer>list=new ArrayList<>();Random random=new Random();for(int i=0;i<100;i++){int val= random.nextInt(1000);list.add(val);}stackTest.test(stack,list);}
}
注:其中long startTime=System.nanoTime();方法是获取一个时间(单位毫秒)
在程序运行前和运行后个添加一个,最后将两个时间相减,得到程序运行时间。

3.时间复杂度分析

二、队列
1.特点
(1)队列也是一种线性数据结构
(2)只能从一端添加元素,另一端取出元素
(3)是一种先进先出的数据结构(FIFO——fist in fist out )
2.具体实现
Java中也可以直接调用队列的方法:

自己的实现:
接口:
package com.algo.lesson.lesson02.queue;public interface Queue_I<T> {void offer(T ele);//入队T poll();//出队T peek();//查找队首元素int getSize();boolean isEmpty();}
方法代码:
package com.algo.lesson.lesson02.queue;import com.algo.lesson.lesson01.MyArr;public class ArrQueue<T>implements Queue_I<T> {private MyArr<T>data;/*private int size;//队列中元素的个数
*/public ArrQueue(){this.data=new MyArr<>(50);}@Overridepublic void offer(T ele) {this.data.add(ele);}@Overridepublic T poll() {if(isEmpty()){return null;}return this.data.removeByIndex(0);}@Overridepublic T peek() {if(isEmpty()){return null;}return this.data.getValueByIndex(0);}@Overridepublic int getSize() {return this.data.getSize();}@Overridepublic boolean isEmpty() {return this.data.isEmpty();}
}
3.出现的问题
入队列时间复杂度为O(n),因为在出队时,元素要前移,会出现假溢出的情况。
所以就出现了循环队列来解决这个问题
循环队列:
front记录队首,tail记录队尾,队尾达到容积时,返回到队头,将空位置补上,可以继续存储数据。
package com.algo.lesson.lesson02.queue;import java.util.Random;/*
基于Java中的数组进行二次封装,制作一个可变数组*/
//泛型:就是类型作为参数
public class LoopArr<T> {private T[] data;//保存数据private int size;//数组中实际存放元素的个数private int front;//队首private int tail;//队尾int capacity;//容积//构造函数public LoopArr(int capacity) {if (capacity <= 0) {this.capacity = 11;} else {this.capacity = capacity + 1;}this.size = 0;this.front = this.tail = 0;this.data = (T[]) (new Object[this.capacity]);}//获取数组中实际存放元素的个数public int getSize() {return this.size;}//获取数组的容积public int getCapacity() {return this.capacity;}//判断数组是否为空public boolean isEmpty() {return this.front == this.tail;}//向数组中添加元素(尾部)public void add(T item) {//判断数组是否满if ((this.tail + 1) % this.capacity == this.front) {//扩容resize((this.capacity-1)*2+1);}//从index位置开始元素需要进行后移this.data[this.tail] = item;this.tail = (this.tail + 1) % this.capacity;//更新this.sizethis.size++;}private void resize(int newCapacity) {System.out.println("resize:" + newCapacity);T[] newData = (T[]) (new Object[newCapacity]);//将原数组驾到新数组里for (int i = 0; i < this.size; i++) {newData[i] = this.data[(this.front+i)%this.capacity];}//改变容器this.data = newData;this.capacity = newCapacity;//将this.front置零this.front=0;this.tail=this.size;}//获取指定位置的值public T getValueByIndex() {if(isEmpty()){return null;}return this.data[this.front];}//移除队首元素public T remove() {if (isEmpty()) {return null;}//删除操作的核心/*1.找到删除的位置2.删除位置之后的元素要前移 arr[j-1]=arr[j]*/T delValue = this.data[this.front];this.front = (this.front + 1) % this.capacity;this.size--;//判断是否缩容if (this.size < this.capacity / 4 && this.capacity / 2 > 0) {resize((this.capacity-1) / 2 +1);}return delValue;}@Overridepublic String toString() {StringBuilder sb = new StringBuilder("[");for (int i = 0; i < this.size; i++) {sb.append(this.data[i]);if (i != this.size - 1) {sb.append(",");}}sb.append("]");return sb.toString();}
}
package com.algo.lesson.lesson02.queue;public class LoopQueue<T> implements Queue_I<T>{private LoopArr<T>data;//容器public LoopQueue(){this.data=new LoopArr<>(100);}@Overridepublic void offer(T ele) {this.data.add(ele);}@Overridepublic T poll() {return this.data.remove();}@Overridepublic T peek() {return this.data.getValueByIndex();}@Overridepublic int getSize() {return this.data.getSize();}@Overridepublic boolean isEmpty() {return this.data.isEmpty();}
}
4.循环队列的复杂度分析

三、栈和队列的互相实现
既然我们了解了栈和队列,知道了这两种数据结构十分相似,也就可以大胆假设以下,可不可以相互实现,不是用上面所写的以数组为底层,而是相互为底层存储。
1.用栈来实现队列
import java.util.Stack;class MyQueue {private Stack<Integer> A;private Stack<Integer> B;public MyQueue() {A = new Stack<>();B = new Stack<>();}public void push(int x) {while (!B.isEmpty()) {A.push(B.pop());}A.push(x);while (!A.isEmpty()) {B.push(A.pop());}}public int pop() {return B.pop();}public int peek() {return B.peek();}public boolean empty() {return B.isEmpty();}
}
2.用队列实现栈
import java.util.LinkedList;
import java.util.Queue;class MyStack {private Queue<Integer> queue1;private Queue<Integer> queue2;public MyStack() {queue1 = new LinkedList<>();queue2 = new LinkedList<>();}public void push(int x) {queue2.add(x);while (!queue1.isEmpty()) {queue2.add(queue1.remove());}Queue<Integer> temp = queue1;queue1 = queue2;queue2 = temp;}public int pop() {return queue1.remove();}public int top() {return queue1.peek();}public boolean empty() {return queue1.isEmpty();}
}
这就是这两种数据结构相互实现的代码
在LeetCode中也有相对应的题目:
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台(栈实现队列)
力扣(LeetCode)官网 - 全球极客挚爱的技术成长平台(队列实现栈)
相关文章:
数据结构——Java实现栈和队列
一、栈 Stack 1.特点 (1)栈是一种线性数据结构 (2)规定只能从栈顶添加元素,从栈顶取出元素 (3)是一种先进后出的数据结构(Last First Out)LIFO 2.具体实现 Java中可…...
【状态压缩】【动态规划】【C++算法】691贴纸拼词
作者推荐 【动态规划】【数学】【C算法】18赛车 本文涉及知识点 状态压缩 动态规划 LeetCode:691 贴纸拼词 我们有 n 种不同的贴纸。每个贴纸上都有一个小写的英文单词。 您想要拼写出给定的字符串 target ,方法是从收集的贴纸中切割单个字母并重新排列它们。如…...
JavaEE之多线程编程:3. 线程的状态(易懂!)
文章目录 一、关于线程的状态二、观察线程的所有状态1. NEW状态2. TERMINATED状态3. RUNNABLE状态4. TIMED_WAITING 一、关于线程的状态 进程最核心的状态,一个是就绪状态,一个是阻塞状态(对于线程同样使用)。 以线程为单位进行调…...
Android13预装APP到data分区
修改步骤与Android11是差不多的,只是有部分代码所在位置不一样。 Android 11内置APP到data/app Android 8(O)预置APP到data/app 默认内置应用到data会出错 1970-01-01 08:03:54.499 1177-1177/system_process I/PackageManager: /data/app/xx changed; collecting…...
Docker registry镜像仓库,私有仓库及harbor管理详解
目录 registry镜像仓库概述 Docker 镜像仓库(Docker Registry): registry 容器: 私有仓库概述 搭建本地私有仓库示例 Harbor概述 harbor架构 详解构成 Harbor由容器构成 Harbor部署示例 环境准备 部署Docker-Compose服…...
用 Rust 过程宏魔法简化 SQL 函数实现
#[function("length(varchar) -> int4")] pub fn char_length(s: &str) -> i32 {s.chars().count() as i32 }这是 RisingWave 中一个 SQL 函数的实现。只需短短几行代码,通过在 Rust 函数上加一行过程宏,我们就把它包装成了一个 SQL…...
OpenSource - 基于 DFA 算法实现的高性能 java 敏感词过滤工具框架
文章目录 sensitive-word创作目的特性变更日志更多资料敏感词控台敏感词标签文件 快速开始准备Maven 引入核心方法判断是否包含敏感词返回第一个敏感词返回所有敏感词默认的替换策略指定替换的内容自定义替换策略 IWordResultHandler 结果处理类使用实例 更多特性样式处理忽略大…...
端杂七杂八系列篇四-Java8篇
后端杂七杂八系列篇四-Java8篇 ① Lombok插件① RequiredArgsConstructor② SneakyThrows③ UtilityClass④ Cleanup ② Lambda 4个常用的内置函数① Function<T, R> - 接受一个输入参数并返回一个结果② Consumer - 接受一个输入参数,并执行某种操作…...
操作系统一些面试
你这个请求队列是属于一写多读对吧,怎么解决冲突的? 可以采用双buffer或者说双缓冲区,一个缓冲区用来写,一个缓冲区用来读,采用交换指针的方法来进行缓存区的交换,这样交换效率是O(1)的,但是交…...
大语言模型
概念 大语言模型(Large Language Model,简称LLM)是一种基于人工智能技术的自然语言处理模型,是指在大量数据上训练的高级人工智能算法,以自上文推理词语概率为核心任务。它通过在海量文本数据上进行训练,学…...
php反序列化之pop链构造(基于重庆橙子科技靶场)
常见魔术方法的触发 __construct() //创建类对象时调用 __destruct() //对象被销毁时触发 __call() //在对象中调用不可访问的方法时触发 __callStatic() //在静态方式中调用不可访问的方法时触发 __get() //调用类中不存在变量时触发(找有连续箭头的…...
k8s---对外服务 ingress
目录 目录 目录 ingress与service ingress的组成 ingress-controller: ingress暴露服务的方式 2.方式二:DaemonSethostnetworknodeSelector DaemonSethostnetworknodeSelector如何实现 3.deploymentNodePort: 虚拟主机的方式实现http代…...
最优解-最长公共子序列
问题描述 最长公共子序列(Longest Common Subsequence,LCS)即求两个序列最长的公共子序列(可以不连续)。比如3 2 1 4 5和1 2 3 4 5两个序列,最长公共子序列为2 4 5 长度为3。解决这个问题必然要使用动态规划。既然要用到动态规划,就要知道状…...
el-tree获取当前选中节点及其所有父节点的id(包含半选中父节点的id)
如下图,我们现在全勾中的有表格管理及其下的子级,而半勾中的有工作台和任务管理及其子级 现在点击保存按钮后,需要将勾中的节点id及该节点对应的父节点,祖先节点的id(包含半选中父节点的id)也都一并传给后端,那这个例子里就应该共传入9个id,我们可以直接将getCheckedK…...
新上线一个IT公司微信小程序
项目介绍 项目背景: 一家IT公司,业务包含以下六大块: 1、IT设备回收 2、IT设备租赁 3、IT设备销售 4、IT设备维修 5、IT外包 6、IT软件开发 通过小程序,提供在线下单,在线制单,在线销售,业务介绍,推广,会员 项目目的: 业务介绍: 包含企业业务介绍 客户需…...
MCAL配置-PWM(EB23.0)
PWM配置项的介绍 一、General 1、PwmDeInitApi 从代码中添加/删除Pwm_17_GtmCcu6_Delnit() API。 TRUE:Pwm_17_GtmCcu6_Delnit() API可供用户使用。 FALSE:Pwm_17_GtmCcu6_Delnit() API对用户不可用。 注意:默认情况下禁用Pwm_17_GtmCcu6_Delnit() …...
v-if和v-for哪个优先级更高?
v-if和v-for哪个优先级更高? 结论: vue2输出的渲染函数是先执行循环,在看条件判断,如果将v-if和v-for写在一个标签内,哪怕只渲染列表中的一小部分,也要重新遍历整个列表,无形造成资源浪费。vu…...
Mapstruct 常用案例(持续更新.).
将A转换为B Mapper(componentModel "spring") public interface DemoConvert {B A2B(A a); }将List转换为List 注意:以下两个都不可缺少,需要先声明单个和集合的同时生命才可 Mapper(componentModel "spring") public interface …...
QT基础篇(10)QT5网络与通信
QT5网络与通信是指在QT5开发环境中使用网络进行数据传输和通信的相关功能和技术。 QT5提供了一套完善的网络模块,包括了TCP、UDP、HTTP等协议的支持,可以方便地在QT应用程序中进行网络通信。通过QT5的网络模块,开发者可以实现客户端和服务器…...
【Leetcode】269.火星词典(Hard)
一、题目 1、题目描述 现有一种使用英语字母的火星语言,这门语言的字母顺序与英语顺序不同。 给你一个字符串列表 words ,作为这门语言的词典,words 中的字符串已经 按这门新语言的字母顺序进行了排序 。 请你根据该词典还原出此语言中已知的字母顺序,并 按字母递增顺序…...
CTF show Web 红包题第六弹
提示 1.不是SQL注入 2.需要找关键源码 思路 进入页面发现是一个登录框,很难让人不联想到SQL注入,但提示都说了不是SQL注入,所以就不往这方面想了 先查看一下网页源码,发现一段JavaScript代码,有一个关键类ctfs…...
golang循环变量捕获问题
在 Go 语言中,当在循环中启动协程(goroutine)时,如果在协程闭包中直接引用循环变量,可能会遇到一个常见的陷阱 - 循环变量捕获问题。让我详细解释一下: 问题背景 看这个代码片段: fo…...
C++:std::is_convertible
C++标志库中提供is_convertible,可以测试一种类型是否可以转换为另一只类型: template <class From, class To> struct is_convertible; 使用举例: #include <iostream> #include <string>using namespace std;struct A { }; struct B : A { };int main…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility
Cilium动手实验室: 精通之旅---20.Isovalent Enterprise for Cilium: Zero Trust Visibility 1. 实验室环境1.1 实验室环境1.2 小测试 2. The Endor System2.1 部署应用2.2 检查现有策略 3. Cilium 策略实体3.1 创建 allow-all 网络策略3.2 在 Hubble CLI 中验证网络策略源3.3 …...
A2A JS SDK 完整教程:快速入门指南
目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库ÿ…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
基于IDIG-GAN的小样本电机轴承故障诊断
目录 🔍 核心问题 一、IDIG-GAN模型原理 1. 整体架构 2. 核心创新点 (1) 梯度归一化(Gradient Normalization) (2) 判别器梯度间隙正则化(Discriminator Gradient Gap Regularization) (3) 自注意力机制(Self-Attention) 3. 完整损失函数 二…...
脑机新手指南(七):OpenBCI_GUI:从环境搭建到数据可视化(上)
一、OpenBCI_GUI 项目概述 (一)项目背景与目标 OpenBCI 是一个开源的脑电信号采集硬件平台,其配套的 OpenBCI_GUI 则是专为该硬件设计的图形化界面工具。对于研究人员、开发者和学生而言,首次接触 OpenBCI 设备时,往…...
