当前位置: 首页 > news >正文

栈(Stack)与队列(Queue,Deque)

前言:

栈与队列在数据结构中用法都相对比较简单,是数据结构中经常用到的两种。

1.栈(Stack)

(1)特点:

 先入后出,后入先出。栈的底层就是一个数组(java原生库中),通过对数组的操作来实现栈的相关操作。栈也是可以用链表(LinkedList)来实现的,在LinkedList这个类中也有push,pop,peek等方法,足以说明栈可以用LinkedList来实现。栈继承了Vector类(这个类中也有一个判空的方法isEmpty() ),可以使用在这个类中的所有非私用方法。

(2)方法:

这里push,pop,empty时间和空间复杂度都为O(1)。 empty判空是定义了一个变量,用来计数。

(3)OJ题:

1)逆波兰表达式求值:

题析:

题解:

import java.util.Stack;
class Solution {public boolean isOperation(String x) {if(x.equals("+") | x.equals("-") | x.equals("*") | x.equals("/")) {return false;}return true;}public int evalRPN(String[] tokens) {Stack<String> stack = new Stack<>();for(String x : tokens) {if(!isOperation(x)) {//如果不是数字int num1 = Integer.parseInt(stack.pop()); //栈顶元素 => 放在右边int num2 = Integer.parseInt(stack.pop()); //栈顶后面一个元素 => 放在左边switch(x) {case "+":stack.push(String.valueOf((num2 + num1)));break;case "-":stack.push(String.valueOf((num2 - num1)));break;case "*":stack.push(String.valueOf((num2 * num1)));break;case "/":stack.push(String.valueOf((num2 / num1)));break;default:break;}}else {stack.push(x);}}return Integer.parseInt(stack.peek());}
}

2)括号匹配: 

题析:

题解:

import java.util.Stack;
class Solution {public boolean isValid(String s) {Stack<Character> stack = new Stack<>();char[] arr = s.toCharArray();for(char x : arr) {if(stack.empty()){stack.push(x);}else {if(stack.peek() == '(' && x == ')' || stack.peek() == '{' && x == '}' || stack.peek() == '[' && x == ']') {stack.pop();}else {stack.push(x);}}}return stack.empty();}
}

3)出栈入栈次序匹配:

题析:

题解:

public class Solution {public boolean IsPopOrder (int[] pushV, int[] popV) {Stack<Integer> stack = new Stack<>();int j = 0;for(int i = 0; i < pushV.length; i++) {stack.push(pushV[i]);while(!stack.isEmpty() && j < popV.length && stack.peek() == popV[j]) {stack.pop();j++;}}if(!stack.isEmpty()) {return false;}return true;}
}

2.队列

队列分为单端队列(Queue)和双端队列(Deque),都是接口,都有先入先出,后入后出的特点。

2.1 单端队列(Queue)

(1)特点:

只有一端可以入,一端可以出。Queue可以用线性表(循环队列),也可以用链表(LinkedList)来实现。

(2)方法:

主要的方法就这三种。需要注意的是这里面Queue接口中没有empty()方法,但由于它是继承了Vector类,所以可以使用isEmpty()方法来判断是否Queue为空。

(3)OJ题:

1)设计循环队列:

题析:

题解:

//法一:设置一个计数变量:count
class MyCircularQueue {//循环队列的底层就是一个数组public int[] arr;//队头public int front;//队尾public int tail;//计数public int count;public MyCircularQueue(int k) {arr = new int[k];}public boolean enQueue(int value) {if(isFull()) {//队列已满return false;}if(tail == arr.length) {tail = 0;}arr[tail] = value;tail++;count++;return true;}public boolean deQueue() {if(isEmpty()) {return false;}front++;if(front == arr.length) {front = 0;}count--;return true;}public int Front() {if(isEmpty()) {return -1;}return arr[front];}public int Rear() {if(isEmpty()) {return -1;}if(isFull()) {}int index = (tail == 0) ? 0 : (tail - 1); return arr[index];}public boolean isEmpty() {return count == 0;}public boolean isFull() {return count == arr.length;}
}
//法二:浪费一个空间
class MyCircularQueue {//循环队列的底层就是一个数组public int[] arr;//队头public int front;//队尾public int tail;public MyCircularQueue(int k) {arr = new int[k + 1];}public boolean enQueue(int value) {if(isFull()) {//队列已满return false;}arr[tail] = value;tail = (tail + 1) % arr.length;return true;}public boolean deQueue() {if(isEmpty()) {return false;}front = (front + 1) % arr.length;return true;}public int Front() {if(isEmpty()) {return -1;}return arr[front];}public int Rear() {if(isEmpty()) {return -1;}int index = (tail == 0) ? (arr.length - 1) : (tail - 1); return arr[index];}public boolean isEmpty() {return tail == front;}public boolean isFull() {return (tail + 1) % arr.length == front;}
}

浪费一个空间的这种写法: 

题中给的示列:

而按我们这种这里的写法: 如果设置长度为3,那么只能放两个元素,所以需要将数组的长度设置为4就能放三个元素了,也就是数组长度设置为k + 1。

 2.2 双端队列

(1)特点:

两端都可以入队出队。Deque可以用线性表(循环队列),也可以用链表(LinkedList)来实现。

(2)方法:

与单端队列的方法都大同小异。 

3.栈与队列相关的OJ题

(1)用栈实现队列

题析:

题解:

class MyQueue {Stack<Integer> stack1;Stack<Integer> stack2;public MyQueue() {stack1 = new Stack<>();stack2 = new Stack<>();}public void push(int x) {stack1.push(x);}public int pop() {if(stack2.isEmpty()) {while(!stack1.isEmpty()) {stack2.push(stack1.pop());}}return stack2.pop();}public int peek() {if(stack2.isEmpty()) {while(!stack1.isEmpty()) {stack2.push(stack1.pop());}}return stack2.peek();}public boolean empty() {return stack1.isEmpty() && stack2.isEmpty();}
}

(2)用队列实现栈:

题析:

题解:

class MyStack {Queue<Integer> queue1;Queue<Integer> queue2;public MyStack() {queue1 = new ArrayDeque<>();queue2 = new ArrayDeque<>();}public void push(int x) {if(!queue1.isEmpty()) {queue1.offer(x);}else if(!queue2.isEmpty()) {queue2.offer(x);}else {//两个都为空,指定放在queue1中queue1.offer(x);}}public int pop() {if(empty()) {return -1;}int i = 0;if(!queue1.isEmpty()) {int size = queue1.size();for(i = 0; i < size- 1; i++) {queue2.offer(queue1.poll());}return queue1.poll();}else {int size = queue2.size();for(i = 0; i < size- 1; i++) {queue1.offer(queue2.poll());}return  queue2.poll();}}public int top() {int i = 0;if(!queue1.isEmpty()) {int size = queue1.size();int x = -1;for(i = 0; i < size; i++) {x = queue1.poll();queue2.offer(x);}return x;}else {int size = queue2.size();int x = -1;for(i = 0; i < size; i++) {x = queue2.poll();queue1.offer(x);}return  x;}}public boolean empty() {//两个队列均为空的时候才能判断该栈为空return queue1.isEmpty() && queue2.isEmpty();}
}

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 亚信安全新一代终端安全TrustOne2024年重磅升级
  • U盘打不开的终极解决方案:原因剖析、恢复策略与预防之道
  • JavaSe系列二十七: Java正则表达式
  • Linux rpm和ssh损坏修复
  • 解析 pdfminer layout.py LAParams类及其应用实例
  • Redis 集群模式
  • 宝兰德参编金融智能体标准,深耕大模型场景化落地
  • ubuntu防火墙指定端口开放设置
  • c#获取本机的MAC地址(附源码)
  • Python学习笔记36:进阶篇(二十五)pygame的使用之事件监听控制切歌和暂停,继续播放
  • 黑马程序员2024最新SpringCloud微服务开发与实战 个人学习心得、踩坑、与bug记录 Day4
  • STM32 IIC详解(软件模拟)
  • 【GameFramework扩展应用】6-1、接入热更新框架HybridCLR
  • 服务器,云、边缘计算概念简单理解
  • 爬虫管理解决方案:让数据收集变得高效且合规
  • 【vuex入门系列02】mutation接收单个参数和多个参数
  • Android 初级面试者拾遗(前台界面篇)之 Activity 和 Fragment
  • CSS3 聊天气泡框以及 inherit、currentColor 关键字
  • CSS中外联样式表代表的含义
  • extjs4学习之配置
  • java 多线程基础, 我觉得还是有必要看看的
  • Java深入 - 深入理解Java集合
  • JS学习笔记——闭包
  • Kibana配置logstash,报表一体化
  • leetcode讲解--894. All Possible Full Binary Trees
  • niucms就是以城市为分割单位,在上面 小区/乡村/同城论坛+58+团购
  • Ruby 2.x 源代码分析:扩展 概述
  • spring学习第二天
  • 好的网址,关于.net 4.0 ,vs 2010
  • 机器学习 vs. 深度学习
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 浅谈JavaScript的面向对象和它的封装、继承、多态
  • 强力优化Rancher k8s中国区的使用体验
  • 如何编写一个可升级的智能合约
  • 时间复杂度与空间复杂度分析
  • 使用putty远程连接linux
  • - 转 Ext2.0 form使用实例
  • No resource identifier found for attribute,RxJava之zip操作符
  • ​MySQL主从复制一致性检测
  • ​ssh免密码登录设置及问题总结
  • #AngularJS#$sce.trustAsResourceUrl
  • #define 用法
  • #define,static,const,三种常量的区别
  • #QT(智能家居界面-界面切换)
  • (1)SpringCloud 整合Python
  • (ISPRS,2023)深度语义-视觉对齐用于zero-shot遥感图像场景分类
  • (Mac上)使用Python进行matplotlib 画图时,中文显示不出来
  • (搬运以学习)flask 上下文的实现
  • (二)hibernate配置管理
  • (附源码)ssm捐赠救助系统 毕业设计 060945
  • (更新)A股上市公司华证ESG评级得分稳健性校验ESG得分年均值中位数(2009-2023年.12)
  • (解决办法)ASP.NET导出Excel,打开时提示“您尝试打开文件'XXX.xls'的格式与文件扩展名指定文件不一致
  • (十五)Flask覆写wsgi_app函数实现自定义中间件
  • (五)Python 垃圾回收机制
  • (一)springboot2.7.6集成activit5.23.0之集成引擎