《Java初阶数据结构》----4.<线性表---Stack栈和Queue队列>
前言
大家好,我目前在学习java。之前也学了一段时间,但是没有发布博客。时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区进行讨论!!!
喜欢我文章的兄弟姐妹们可以点赞,收藏和评论我的文章。喜欢我的兄弟姐妹们以及也想复习一遍java知识的兄弟姐妹们可以关注我呦,我会持续更新滴,
望支持!!!!!!一起加油呀!!!!
语言只是工具,不能决定你好不好找工作,决定你好不好找工作的是你的能力!!!!!
学历本科及以上就够用了!!!!!!!!!!!!!!!!!!!!!!
本篇博客主要讲解Java基础语法中的
一、栈
1. 栈的概念
2. 栈的使用
3. 栈的模拟实现
4. 栈的常见编程题
二、队列
1. 队列的概念
2. 队列的使用
3.队列的模拟实现
4.队列的循环设计
三、双端队列
一、栈(stack)
1.1 栈的概念
栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。
栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。

Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安 全的。
1.2 栈的使用

代码示例:
public static void main(String[] args) {Stack<Integer> s = new Stack();s.push(1);s.push(2);s.push(3);s.push(4);System.out.println(s.size()); // 获取栈中有效元素个数---> 4System.out.println(s.peek()); // 获取栈顶元素---> 4s.pop(); // 4出栈,栈中剩余1 2 3,栈顶元素为3System.out.println(s.pop()); // 3出栈,栈中剩余1 2 栈顶元素为3if(s.empty()){System.out.println("栈空");}else{System.out.println(s.size());}
}
1.3 栈的模拟实现
变量的定义、包含定义一个数组存储栈、记录栈中元素个数、
定义一个静态常量便于初始化栈
private int[] elem;//定义一个数组来存储栈中元素private int useSize;//记录栈中元素private static final int DEFAULT_CAPACITY = 10;//定义一个静态常量
获取栈的长度的方法
public int getUseSize() {return useSize;}
栈的有参构造方法。构造一个容量为DEFAULT_CAPACITY的栈
//构造一个容量为DEFAULT_CAPACITY的栈public MyStack(){this.elem = new int[DEFAULT_CAPACITY];}
检测栈是否满了
//检测栈是否满了private boolean isFull(){return this.useSize == this.elem.length;}
入栈:将val放入栈
//将val放入栈public void push(int val){if (isFull()){this.elem = Arrays.copyOf(this.elem,2*this.elem.length);}this.elem[useSize++] = val;}
出栈: 将栈顶元素取出并返回
//将栈顶元素取出并返回public int pop(){if (isEmpty()){throw new EmptyException("Stack为空!");}return elem[--useSize];}
获取栈顶元素
//获取栈顶元素public int peek(){if (isEmpty()){throw new EmptyException("Stack为空!");}return elem[useSize-1];}
检测栈是否为空
//检测栈是否为空private boolean isEmpty(){return this.useSize == 0;}
1.4 栈的常见编程题
1.有效的括号
public boolean isValid(String s) {Stack<Character> stack = new Stack<>();
//判断是否为有效的括号,具有先进后匹配的特点,因此我们用栈。首先创建一个栈int len = s.length(); //首先得到字符串长度if (len == 0) { //如果字符串为空,则返回truereturn true;}if (len % 2 == 1) { //括号成双成对,因此如果字符串为奇数,那么直接返回falsereturn false; } else { //如果为偶数,符合预期则,将字符串转字符数组。遍历这个字符数组char[] chars = s.toCharArray();for (char ch : chars) { if (ch == '(' || ch == '[' || ch == '{') { //如果为左括号,则入栈。stack.push(ch);}if (!stack.empty()) { //如果有左括号,到这里栈一定不为空。如果栈为空,则返回false,因为先得有左括号才会是有效括号//接下来判断右括号,如果遍历到右括号,那么必有栈顶元素与之配对才会是有效括号,并出栈栈顶元素。否则返回false。if (ch == '}') {if (stack.pop() != '{') {return false;}}if (ch == ']') {if (stack.pop() != '[') {return false;}}if (ch == ')') {if (stack.pop() != '(') {return false;}}} else { return false;}}} //最终判断栈是否为空,若全是左括号,那么就没有出栈。因此如果栈内有元素则为false。若匹配成功//栈为空,返回truereturn stack.empty();}
2.逆波兰表达式求值
import java.util.Stack;
//运算方法是将数字入栈,如果碰到运算符号。则出栈将第一个出栈元素放在运算符右边,第二个出栈元素放入运算符左边
//计算这个结果,并将这个计算结果入栈。重复以上操作。即可计算出逆波兰表达式的值。
public class Solution {public int evalRPN(String[] tokens) {Stack<Integer> stack = new Stack<>();int right;int left; for (String token:tokens) {switch (token){case "+":stack.push(stack.pop()+stack.pop());break;case "-":right = stack.pop();left = stack.pop();stack.push(left-right);break;case "*":stack.push(stack.pop()*stack.pop());break;case "/":right = stack.pop();left = stack.pop();stack.push(left/right);break;default:stack.push(Integer.parseInt(token)); //注意这里放入栈的时候要将字符串转整型类型}}return stack.peek();}
}
1.运算方法是将数字入栈,如果碰到运算符号。则出栈将第一个出栈元素放在运算符右边,第二个出栈元素放入运算符左边
2.计算这个结果,并将这个计算结果入栈。重复以上操作。即可计算出逆波兰表达式的值。
3.栈的压入、弹出序列
import java.util.Stack;
public class Solution {public boolean IsPopOrder(int [] pushA,int [] popA) {int n = pushA.length;//辅助栈Stack<Integer> s = new Stack<>();//遍历入栈的下标int j = 0;//遍历出栈的数组for(int i = 0; i < n; i++){//入栈:栈为空或者栈顶不等于出栈数组while(j < n && (s.isEmpty() || s.peek() != popA[i])){s.push(pushA[j]);j++;}//栈顶等于出栈数组if(s.peek() == popA[i])s.pop();//不匹配序列elsereturn false;}return true;}
}
4.最小栈
class MinStack {Deque<Integer> xStack;Deque<Integer> minStack;public MinStack() {xStack = new LinkedList<Integer>();minStack = new LinkedList<Integer>();minStack.push(Integer.MAX_VALUE);}public void push(int x) {xStack.push(x);minStack.push(Math.min(minStack.peek(), x));}public void pop() {xStack.pop();minStack.pop();}public int top() {return xStack.peek();}public int getMin() {return minStack.peek();}
}
1.5栈的应用场景
将递归转化为循环
比如:逆序打印链表
递归方式
// 递归方式
void printList(Node head){if(null != head){printList(head.next);System.out.print(head.val + " ");}
}
循环方式
// 循环方式
void printList(Node head){if(null == head){return;}Stack<Node> s = new Stack<>();// 将链表中的结点保存在栈中Node cur = head;while(null != cur){s.push(cur);cur = cur.next;}// 将栈中的元素出栈while(!s.empty()){System.out.print(s.pop().val + " ");}
}
二、队列
2.1队列的概念
队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)。
入队列:进行插入操作的一端称为队尾(Tail/Rear)
出队列:进行删除操作的一端称为队头 (Head/Front)

在Java中,Queue是个接口,底层是通过链表实现的。
2.2 队列的使用

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。
public static void main(String[] args) {Queue<Integer> q = new LinkedList<>();q.offer(1);q.offer(2);q.offer(3);q.offer(4);q.offer(5); // 从队尾入队列System.out.println(q.size());System.out.println(q.peek()); // 获取队头元素q.poll();System.out.println(q.poll()); // 从队头出队列,并将删除的元素返回if(q.isEmpty()){System.out.println("队列空");}else{System.out.println(q.size());}
}
2.3 队列模拟实现
队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前面线性表的学习了解到常见的空间类型有 两种:顺序结构 和 链式结构。思考下:队列的实现使用顺序结构还是链式结构好?
定义变量、用内部类定义队列的的节点、队头、队尾、队员数
static class ListNode{private int val;private ListNode prev;private ListNode next;public ListNode(int val){this.val = val;}private ListNode front;//队头private ListNode rear;//队尾private int useSize;//队员数}
得到队员数
public int getUseSize() {return useSize;}
入队
//入队操作,相当于头插法public void offer(int x){ListNode node = new ListNode(x);if(front == null){front = rear = node;}else {node.next = front;front.prev = node;front = node;}useSize++;}
出队
//出队操作,相当于删除尾节点public int poll(){if(rear == null){return -1;}int ret = rear.val;if(front == rear){front = null;rear = null;return ret;}rear = rear.prev;rear.next = null;useSize--;return ret;}
获取队头元素
//获取队头元素public int peek(){if(front == null){return -1;}return front.val;}
检测队列是否为空
//检测队列是否为空public boolean isEmpty(){return this.useSize == 0;}
2.4 循环队列
实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解的生产者消费者模型就可以就会使用循环队列。 环形队列通常使用数组实现。
数组下标循环的小技巧
1. 下标最后再往后(offset 小于 array.length): index = (index + offset) % array.length

2. 下标最前再往前(offset 小于 array.length): index = (index + array.length - offset) % array.length
如何区分空与满
1. 通过添加 size 属性记录
2. 保留一个位置
3. 使用标记
三、双端队列 (Deque)
双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。
那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。

Deque是一个接口,使用时必须创建LinkedList的对象。
在实际工程中,使用Deque接口是比较多的,栈和队列均可以使用该接口。
Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现
2.5设计循环队列
class MyCircularQueue {private int front;private int rear;private int capacity;private int[] elements;public MyCircularQueue(int k) {capacity = k + 1;elements = new int[capacity];rear = front = 0;}public boolean enQueue(int value) {if (isFull()) {return false;}elements[rear] = value;rear = (rear + 1) % capacity;return true;}public boolean deQueue() {if (isEmpty()) {return false;}front = (front + 1) % capacity;return true;}public int Front() {if (isEmpty()) {return -1;}return elements[front];}public int Rear() {if (isEmpty()) {return -1;}return elements[(rear - 1 + capacity) % capacity];}public boolean isEmpty() {return rear == front;}public boolean isFull() {return ((rear + 1) % capacity) == front;}
}
四、面试题
1.用队列实现栈
class MyStack {Queue<Integer> queue1;Queue<Integer> queue2;/** Initialize your data structure here. */public MyStack() {queue1 = new LinkedList<Integer>();queue2 = new LinkedList<Integer>();}/** Push element x onto stack. */public void push(int x) {queue2.offer(x);while (!queue1.isEmpty()) {queue2.offer(queue1.poll());}Queue<Integer> temp = queue1;queue1 = queue2;queue2 = temp;}/** Removes the element on top of the stack and returns that element. */public int pop() {return queue1.poll();}/** Get the top element. */public int top() {return queue1.peek();}/** Returns whether the stack is empty. */public boolean empty() {return queue1.isEmpty();}
}
2.用栈实现队列
class MyQueue {Deque<Integer> inStack;Deque<Integer> outStack;public MyQueue() {inStack = new ArrayDeque<Integer>();outStack = new ArrayDeque<Integer>();}public void push(int x) {inStack.push(x);}public int pop() {if (outStack.isEmpty()) {in2out();}return outStack.pop();}public int peek() {if (outStack.isEmpty()) {in2out();}return outStack.peek();}public boolean empty() {return inStack.isEmpty() && outStack.isEmpty();}private void in2out() {while (!inStack.isEmpty()) {outStack.push(inStack.pop());}}
}
相关文章:
《Java初阶数据结构》----4.<线性表---Stack栈和Queue队列>
前言 大家好,我目前在学习java。之前也学了一段时间,但是没有发布博客。时间过的真的很快。我会利用好这个暑假,来复习之前学过的内容,并整理好之前写过的博客进行发布。如果博客中有错误或者没有读懂的地方。热烈欢迎大家在评论区…...
Android SurfaceFlinger——关联EGL三要素(二十七)
通过前面的文章我们得到了 EGL 的三要素——Display、Surface 和 Context。其中,Display 是一个图形显示系统或者硬件屏幕,Surface 代表一个可以被渲染的图像缓冲区,Context 包含了 OpenGL ES 的状态信息和资源,它是执行 OpenGL 命令的环境。下一步就是调用 eglMakeCurrent…...
Unity3D之TCP网络通信(客户端)
文章目录 概述TCP核心类异步机制 Unity中创建TCP客户端Unity中其它脚本获取TCP客户端接受到的数据后续改进 本文将以Unity3D应用项目作为客户端去连接制定的服务器为例进行相关说明。 Unity官网参考资料: https://developer.unity.cn/projects/6572ea1bedbc2a001ef…...
Kotlin 中 标准库函数
在 Kotlin 中,标准库提供了许多实用的函数,这些函数可以帮助简化代码、提高效率,以下是一些常用的标准库函数及其功能: let: let 函数允许你在对象上执行一个操作,并返回结果。它通常与安全调用操作符 ?. 一起使用&a…...
【教学类-69-01】20240721铠甲勇士扑克牌(随机14个数字+字母)涂色(男孩篇)
背景需求: 【教学类-68-01】20240720裙子涂色(女孩篇)-CSDN博客文章浏览阅读250次。【教学类-68-01】20240720裙子涂色(女孩篇)https://blog.csdn.net/reasonsummer/article/details/140578153 前期制作了女孩涂色延…...
Adobe“加速”创意人士开启设计新篇章
近日,Adobe公司宣布了其行业领先的专业设计应用程序——Adobe Illustrator和Adobe Photoshop的突破性创新。这一重大更新不仅为创意专业人士带来了前所未有的设计可能性和工作效率提升,还让不论是插画师、设计师还是摄影师,都能从中受益并创作…...
释疑 803-(1)概述 精炼提纯版
目录 习题 1-01计算机网络可以向用户提供哪些服务? 1-02 试简述分组交换的要点。 1-03 试从多个方面比较电路交换、报文交换和分组交换的主要优缺点。 1-05 互联网基础结构的发展大致分为哪几个阶段?请指出这几个阶段最主要的特点。 1-06 简述互联网标准制定的几个阶段…...
人工智能与机器学习原理精解【6】
文章目录 数值优化基础理论凹凸性定义在国外与国内存在不同国内定义国外定义总结示例与说明注意事项 国内凹凸性二阶定义的例子凹函数例子凸函数例子 凸函数(convex function)的开口方向凸函数的二阶导数凸函数的二阶定义单变量函数的二阶定义多变量函数…...
JDK、JRE、JVM之间的关系
JDK是Java的开发环境,用JDK开发了JAVA程序后,通过JDK中的编译程序(javac)将java文件编译成字节码文件,作为运行环境的JRE,字节码文件在JRE上运行,作为虚拟机的JVM解析这些字节码,映射…...
redis构建集群时,一直Waiting for the cluster to join
redis构建集群时,一直Waiting for the cluster to join 前置条件参考 前置条件 这是我搭建的集群相关信息,三台虚拟机,分别是一主一从。在将所有虚拟机中redis服务器用到的tcp端口都打开之后,进行构建集群。但是出现上面的情况。 …...
C++之类与对象(2)
前言 今天将步入学习类的默认成员函数,本节讲解其中的构造函数和析构函数。 1.类的默认成员函数 在 C 中,如果一个类没有显式定义某些成员函数,编译器会自动为该类生成默认的成员函数。以下是编译器可能会生成的默认成员函数: 默…...
「树形结构」基于 Antd 实现一个动态增加子节点+可拖拽的树
效果 如图所示 实现 import { createRoot } from react-dom/client; import React, { useState } from react; import { Tree, Input, Button } from antd; import { PlusOutlined } from ant-design/icons;const { TreeNode } Tree; const { Search } Input;const ini…...
ubuntu那些ppa源在哪
Ubuntu中的 PPA 终极指南 - UBUNTU粉丝之家 什么是PPA PPA 代表个人包存档。 PPA 允许应用程序开发人员和 Linux 用户创建自己的存储库来分发软件。 使用 PPA,您可以轻松获取较新的软件版本或官方 Ubuntu 存储库无法提供的软件。 为什么使用PPA? 正如…...
20240724-然后用idea创建一个Java项目/配置maven环境/本地仓储配置
1.创建一个java项目 (1)点击页面的create project,然后next (2)不勾选,继续next (3)选择新项目名称,新项目路径,然后Finsh,在新打开的页面选择…...
PaddleOCR-PP-OCRv4推理详解及部署实现(下)
目录 前言1. 检测模型1.1 预处理1.2 后处理1.3 推理 2. 方向分类器模型2.1 预处理2.2 后处理2.3 推理 3. 识别模型3.1 预处理3.2 后处理3.3 推理 4. PP-OCRv4部署4.1 源码下载4.2 环境配置4.2.1 配置CMakeLists.txt4.2.2 配置Makefile 4.3 ONNX导出4.4 engine生成4.4.1 检测模型…...
【Golang 面试基础题】每日 5 题(二)
✍个人博客:Pandaconda-CSDN博客 📣专栏地址:http://t.csdnimg.cn/UWz06 📚专栏简介:在这个专栏中,我将会分享 Golang 面试中常见的面试题给大家~ ❤️如果有收获的话,欢迎点赞👍收藏…...
状态模式与订单状态机的实现
状态模式 状态模式(State Design Pattern)是一种行为设计模式,用于在对象的内部状态改变时改变其行为。这种模式可以将状态的变化封装在状态对象中,使得对象在状态变化时不会影响到其他代码,提升了代码的灵活性和可维…...
【MSP430】MSP430是什么?与STM32对比哪个性能更佳?
一、MSP430是什么? MSP430F5529LP是一款由德州仪器(TI)推出的16位微控制器单元(MCU)开发板,具有USB功能,内存配置为128KB闪存和8KB RAM,工作频率高达25MHz。 这款MCU以其高性能和多…...
Win11 操作(四)g502鼠标连接电脑不亮灯无反应
罗技鼠标连接电脑不亮灯无反应 前言 罗技技术💩中💩,贴吧技术神中神! 最近买了一个g502,结果买回来直接插上电脑连灯都不亮,问了一下客服。客服简单的让我换接口,又是下载ghub之类的…...
自定义QDialog使用详解
自定义QDialog使用详解 一、创建 QDialog 对象二、QDialog设置布局三、QDialog控制模态行为3.1 模态和非模态区别3.2 QDialog的模态使用四、使用 QDialogButtonBox五、处理对话框的结果六、使用 QDialog 的信号和槽QDialog是Qt框架中用于创建对话框窗口的基本类。对话框窗口通常…...
浏览器访问 AWS ECS 上部署的 Docker 容器(监听 80 端口)
✅ 一、ECS 服务配置 Dockerfile 确保监听 80 端口 EXPOSE 80 CMD ["nginx", "-g", "daemon off;"]或 EXPOSE 80 CMD ["python3", "-m", "http.server", "80"]任务定义(Task Definition&…...
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…...
在rocky linux 9.5上在线安装 docker
前面是指南,后面是日志 sudo dnf config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo sudo dnf install docker-ce docker-ce-cli containerd.io -y docker version sudo systemctl start docker sudo systemctl status docker …...
Objective-C常用命名规范总结
【OC】常用命名规范总结 文章目录 【OC】常用命名规范总结1.类名(Class Name)2.协议名(Protocol Name)3.方法名(Method Name)4.属性名(Property Name)5.局部变量/实例变量(Local / Instance Variables&…...
[ICLR 2022]How Much Can CLIP Benefit Vision-and-Language Tasks?
论文网址:pdf 英文是纯手打的!论文原文的summarizing and paraphrasing。可能会出现难以避免的拼写错误和语法错误,若有发现欢迎评论指正!文章偏向于笔记,谨慎食用 目录 1. 心得 2. 论文逐段精读 2.1. Abstract 2…...
《通信之道——从微积分到 5G》读书总结
第1章 绪 论 1.1 这是一本什么样的书 通信技术,说到底就是数学。 那些最基础、最本质的部分。 1.2 什么是通信 通信 发送方 接收方 承载信息的信号 解调出其中承载的信息 信息在发送方那里被加工成信号(调制) 把信息从信号中抽取出来&am…...
免费PDF转图片工具
免费PDF转图片工具 一款简单易用的PDF转图片工具,可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件,也不需要在线上传文件,保护您的隐私。 工具截图 主要特点 🚀 快速转换:本地转换,无需等待上…...
基于单片机的宠物屋智能系统设计与实现(论文+源码)
本设计基于单片机的宠物屋智能系统核心是实现对宠物生活环境及状态的智能管理。系统以单片机为中枢,连接红外测温传感器,可实时精准捕捉宠物体温变化,以便及时发现健康异常;水位检测传感器时刻监测饮用水余量,防止宠物…...
前端调试HTTP状态码
1xx(信息类状态码) 这类状态码表示临时响应,需要客户端继续处理请求。 100 Continue 服务器已收到请求的初始部分,客户端应继续发送剩余部分。 2xx(成功类状态码) 表示请求已成功被服务器接收、理解并处…...
解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...
