《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框架中用于创建对话框窗口的基本类。对话框窗口通常…...
基于算法竞赛的c++编程(28)结构体的进阶应用
结构体的嵌套与复杂数据组织 在C中,结构体可以嵌套使用,形成更复杂的数据结构。例如,可以通过嵌套结构体描述多层级数据关系: struct Address {string city;string street;int zipCode; };struct Employee {string name;int id;…...
未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?
编辑:陈萍萍的公主一点人工一点智能 未来机器人的大脑:如何用神经网络模拟器实现更智能的决策?RWM通过双自回归机制有效解决了复合误差、部分可观测性和随机动力学等关键挑战,在不依赖领域特定归纳偏见的条件下实现了卓越的预测准…...
【网络安全产品大调研系列】2. 体验漏洞扫描
前言 2023 年漏洞扫描服务市场规模预计为 3.06(十亿美元)。漏洞扫描服务市场行业预计将从 2024 年的 3.48(十亿美元)增长到 2032 年的 9.54(十亿美元)。预测期内漏洞扫描服务市场 CAGR(增长率&…...
【大模型RAG】Docker 一键部署 Milvus 完整攻略
本文概要 Milvus 2.5 Stand-alone 版可通过 Docker 在几分钟内完成安装;只需暴露 19530(gRPC)与 9091(HTTP/WebUI)两个端口,即可让本地电脑通过 PyMilvus 或浏览器访问远程 Linux 服务器上的 Milvus。下面…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
【算法训练营Day07】字符串part1
文章目录 反转字符串反转字符串II替换数字 反转字符串 题目链接:344. 反转字符串 双指针法,两个指针的元素直接调转即可 class Solution {public void reverseString(char[] s) {int head 0;int end s.length - 1;while(head < end) {char temp …...
微服务商城-商品微服务
数据表 CREATE TABLE product (id bigint(20) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT 商品id,cateid smallint(6) UNSIGNED NOT NULL DEFAULT 0 COMMENT 类别Id,name varchar(100) NOT NULL DEFAULT COMMENT 商品名称,subtitle varchar(200) NOT NULL DEFAULT COMMENT 商…...
dify打造数据可视化图表
一、概述 在日常工作和学习中,我们经常需要和数据打交道。无论是分析报告、项目展示,还是简单的数据洞察,一个清晰直观的图表,往往能胜过千言万语。 一款能让数据可视化变得超级简单的 MCP Server,由蚂蚁集团 AntV 团队…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
视频行为标注工具BehaviLabel(源码+使用介绍+Windows.Exe版本)
前言: 最近在做行为检测相关的模型,用的是时空图卷积网络(STGCN),但原有kinetic-400数据集数据质量较低,需要进行细粒度的标注,同时粗略搜了下已有开源工具基本都集中于图像分割这块,…...
