Java_栈_队列

文章目录

  • 一、栈(Stack)
    • 1.概念
    • 2.栈的使用
    • 3.栈的模拟实现
      • 1、定义接口
      • 2、定义栈
      • 3、成员
      • 4、构造方法
      • 5、判断空间是否满 full
      • 6、入栈 push
      • 7、出栈 pop
      • 8、获取栈顶元素 peek
      • 9、获取栈中有效元素个数 size
      • 10、检测栈是否为空 empty
      • 完整代码
    • 4.练习
      • 1、有效括号
      • 2、逆波兰表达式求值
      • 3、栈的压入,弹出序列
      • 4、最小栈
    • 5. 概念区分
  • 二、队列
    • 1.概念
    • 2.队列的使用
    • 3.模拟实现
      • 1、成员
      • 2、入队列 offer
      • 3、出队列 poll
      • 4、获取队头元素 peek
      • 5、获取队列中有效元素个数 size
      • 6、检查队列是否为空 isEmpty
      • 完整代码
  • 三、其他队列
    • 1.循环队列
      • 设计循环队列
    • 2.双端队列
    • 3.练习


一、栈(Stack)

1.概念

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。
压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。
在这里插入图片描述

2.栈的使用

方法功能
Stack()构造一个空的栈
E push(E e)将e入栈
E pop()将栈顶元素出栈
E peek()获取栈顶元素
int size()获取栈中有效元素个数
boolean empty()检查栈是否为空
    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());System.out.println(s.peek());s.pop();System.out.println(s.pop());if(s.empty()){System.out.println("栈空");}else{System.out.println(s.size());}}

在这里插入图片描述

3.栈的模拟实现

在这里插入图片描述
从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是Vector是线程安全的。

1、定义接口

public interface IStack {void push(int x);int pop();int peek();int size();boolean empty();//判断是否满boolean full();
}

2、定义栈

public class MyStack implements IStack{@Overridepublic void push(int x) {}@Overridepublic int pop() {return 0;}@Overridepublic int peek() {return 0;}@Overridepublic int size() {return 0;}@Overridepublic boolean empty() {return false;}@Overridepublic boolean full() {return false;}
}

3、成员

存储数据的数组:

    private  int usedSize;

有效数据的个数:

    private  int usedSize;

默认大小:

    private  static  final  int DEFAULT_CAPACITY = 10;

4、构造方法

    public MyStack(){elem =new int[DEFAULT_CAPACITY];}

5、判断空间是否满 full

	@Overridepublic boolean full() {if(usedSize ==elem.length){return  true;}return false;}

6、入栈 push

    @Overridepublic void push(int x) {if(full()){elem = Arrays.copyOf(elem,elem.length*2);}elem[usedSize++] =x;}

7、出栈 pop

public class EmptyException extends RuntimeException{public EmptyException(String msg){super(msg);}}
-------------------------------------@Overridepublic int pop() {if(empty()){//抛异常throw new EmptyException("栈空,出栈异常");}int old = elem[usedSize--];//如果是引用就需要置空return old;}

8、获取栈顶元素 peek

    @Overridepublic int peek() {if(empty()){//抛异常throw new EmptyException("栈空");}return elem[usedSize-1];}

9、获取栈中有效元素个数 size

   @Overridepublic int size() {return usedSize;}

10、检测栈是否为空 empty

    @Overridepublic boolean empty() {return  usedSize==0;}

完整代码

public class EmptyException extends RuntimeException{public EmptyException(String msg){super(msg);}}----------------------------
public interface IStack {void push(int x);int pop();int peek();int size();boolean empty();//判断是否满boolean full();
}----------------------------------
import java.util.Arrays;public class MyStack  implements IStack{private  int [] elem;private  int usedSize;private  static  final  int DEFAULT_CAPACITY = 10;public MyStack(){elem =new int[DEFAULT_CAPACITY];}@Overridepublic boolean full() {if(usedSize ==elem.length){return  true;}return false;}@Overridepublic void push(int x) {if(full()){elem = Arrays.copyOf(elem,elem.length*2);}elem[usedSize++] =x;}@Overridepublic int pop() {if(empty()){//抛异常throw new EmptyException("栈空,出栈异常");}int old = elem[usedSize--];return old;}@Overridepublic int peek() {if(empty()){//抛异常throw new EmptyException("栈空");}return elem[usedSize-1];}@Overridepublic int size() {return usedSize;}@Overridepublic boolean empty() {return  usedSize==0;}
}

4.练习

1、有效括号

有效括号
开一个栈,遇到左括号进栈,遇到右括号检查栈顶和遇到右括号是否匹配。

class Solution {public boolean isValid(String s) {Stack<Character> st = new Stack<>();for(int i = 0;i<s.length();i++){char c =s.charAt(i);if(c=='('||c=='{'||c=='['){st.push(c);}else{if(c==')'&&!st.empty()){if(st.peek()!='('){return false;}st.pop();}else if(c=='}'&&!st.empty()){if(st.peek()!='{'){return false;}st.pop();}else if(c==']'&&!st.empty()){if(st.peek()!='['){return false;}st.pop();}else {return false;}}}if(st.empty()){return true;}return  false;}
}

2、逆波兰表达式求值

逆波兰表达式
判断是操作数还是算符,如果是操作数转Int存在栈,不是就按算符进行运算。

class Solution {boolean isOperation(String s){if(s.equals("+")||s.equals("-")||s.equals("*")||s.equals("/")){return  true;}return false;}public int evalRPN(String[] tokens) {Stack<Integer > st = new Stack<>();for(int i = 0;i<tokens.length;i++){String s  =  tokens[i];if(isOperation(s)){int right  = 0;int left=0 ;if(st.size()>=2){right = st.pop();left = st.pop();}if(s.equals("+")){st.push(left+right);}else if(s.equals("-")){st.push(left-right);}else if(s.equals("*")){st.push(left*right);}else if(s.equals("/")){st.push(left/right);}}else{int temp = Integer.parseInt(s);st.push(temp);}}return st.peek();}
}

3、栈的压入,弹出序列

栈的压入,弹出序列
先创建一个栈模拟压入,循环检查是否可以出栈,如果符合就出栈,不符合继续压入,直到全部压入但不能出栈,即为不符合弹出序列。

import java.util.*;public class Solution {/*** 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可*** @param pushV int整型一维数组* @param popV int整型一维数组* @return bool布尔型*/public boolean IsPopOrder (int[] pushV, int[] popV) {Stack<Integer> st = new Stack<>();int cur1= 0;int cur2 =0;int len = pushV.length;while(cur1<len||cur2<len){if(cur1<len){st.push(pushV[cur1]);}while(cur2<len){if(!st.empty()&&st.peek()==popV[cur2]){st.pop();cur2++;}else {if(cur1<len){break;}else{return false;}}}cur1++;}return st.empty();}
}

4、最小栈

最小栈
开两个栈,一个存最小值的栈,一个就是普通的栈。在入栈的时候,判断存最小值的栈是否为空,空就同时入这两个栈,不为空就要比较存最小值的栈上面的值和新入的值,如果比最小栈的值还小或等于就同时入两栈,否则只入普通栈。

class MinStack {private  Stack<Integer> stack;private  Stack<Integer> minStack;public MinStack() {stack =new Stack<>();minStack = new Stack<>();}public void push(int val) {stack.push(val);if(minStack.empty()){minStack.push(val);}else{if(minStack.peek()>=val){minStack.push(val);}}}public void pop() {if(minStack.peek().equals(stack.peek())){minStack.pop();}stack.pop();}public int top() {return  stack.peek();}public int getMin() {return minStack.peek();}
}

5. 概念区分

栈、虚拟机栈、栈帧有什么区别?
栈:数据结构
虚拟机栈:JVM划分的一款内存而已
栈帧:调用方法的时候会在虚拟机当中给这个方法开辟一块内存

二、队列

1.概念

队列:只允许在一端进行插入数据操作,在另一端就进行删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)
入队列:进行插入操作的一端称为队尾(Tail/Rear)
出队列:进行删除操作的一端称为队头(Head/Front)
在这里插入图片描述

2.队列的使用

在Java中,Queue是个接口,底层是通过链表实现的。
在这里插入图片描述

方法功能
boolean offer(E e)入队列
E poll()出队列
peek()获取队头元素
int size()获取队列中有效元素个数
boolean isEmpty()检查队列是否为空

注意:Queue是个接口,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接口。

    public static void main(String[] args) {Queue<Integer> queue = new LinkedList<>();queue.offer(1);queue.offer(2);queue.offer(3);System.out.println(queue.size());System.out.println(queue.peek());queue.poll();System.out.println(queue.isEmpty());System.out.println(queue.poll());System.out.println(queue.poll());System.out.println(queue.isEmpty());}

在这里插入图片描述

3.模拟实现

1、成员

双向链表节点

    static class ListNode{public int val;public ListNode next;public ListNode prev;public ListNode(int val){this.val =val;}}

头尾引用

    public ListNode head;public ListNode last;

节点个数

    public int size;

2、入队列 offer

   boolean offer(int val){ListNode node = new ListNode(val);if(head==null){head = node;last = node;}else{last.next = node;node.prev = last;last = node;}size++;return true;}

3、出队列 poll

public  int poll(){if(head==null){return -1;}int ret  = head.val;if(head.next==null){head =null;last  = null;return ret;}head.next.prev = null;head = head.next;return ret;}

4、获取队头元素 peek

    public int peek(){if(head==null){return -1;}return head.val;}

5、获取队列中有效元素个数 size

   public  int size(){return  size;}

6、检查队列是否为空 isEmpty

    public  boolean isEmpty(){return size==0;}

完整代码

package queuedemo;import java.util.List;public class MyLinkQueue  {static class ListNode{public int val;public ListNode next;public ListNode prev;public ListNode(int val){this.val =val;}}public ListNode head;public ListNode last;public int size;boolean offer(int val){ListNode node = new ListNode(val);if(head==null){head = node;last = node;}else{last.next = node;node.prev = last;last = node;}size++;return true;}public  int poll(){if(head==null){return -1;}size--;int ret  = head.val;if(head.next==null){head =null;last  = null;return ret;}head.next.prev = null;head = head.next;return ret;}public int peek(){if(head==null){return -1;}return head.val;}public  int size(){return  size;}public  boolean isEmpty(){return size==0;}}

三、其他队列

1.循环队列

实际中我们有时还会使用一种队列叫循环队列。如操作系统课程讲解生产者消费者模型时可以就会使用循环队列。环形队列通常使用数组实现。
在这里插入图片描述
问题:


如何判断是空还是满?
解决空还是满有很多种方案:
1.使用usedSize进行记录
2.浪费一个空间来表示满
3.使用标记


如何从7下标来到0下标?
(队尾指针+1)%len

设计循环队列

设计循环队列


class MyCircularQueue {public int [] elem;int front = 0;int rear  = 0;public MyCircularQueue(int k) {elem = new int[k+1];}public boolean enQueue(int value) {if(isFull()){return  false; }elem[rear] = value;rear = (rear+1)%elem.length;return true;}public boolean deQueue() {if(isEmpty()){return false;}front = (front+1)%elem.length;return true;}public int Front() {if(isEmpty()){return-1;}return elem[front];}public int Rear() {if(isEmpty()){return -1;}int temp = (rear-1+elem.length)%elem.length;return  elem[temp];}public boolean isEmpty() {return  front==rear;}public boolean isFull() {return  (rear+1)%elem.length==front;}
}

2.双端队列

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。那就说明元素可以从队头出队和入队,也可以从队尾出队和入队。
Deque是一个接口,使用时必须创建LinkedList的对象。

Deque<Integer> stack = new ArrayDeque<>();//双端队列的线性实现
Deque<Integer> queue = new LinkedList<>();//双端队列的链式实现

3.练习

队列实现栈

class MyStack {Queue<Integer> que1;Queue<Integer> que2;public MyStack() {que1 = new LinkedList<>();que2 = new LinkedList<>();}public void push(int x) {if(que1.isEmpty()&&que2.isEmpty()){que1.offer(x);}else{if(que1.isEmpty()){que2.offer(x);}else{que1.offer(x);}}}public int pop() {int size ;if(que1.isEmpty()){size = que2.size();for(int i = 0;i<size-1;i++){que1.offer(que2.poll());}return que2.poll();}else{size = que1.size();for(int i = 0;i<size-1;i++){que2.offer(que1.poll());}return que1.poll();}}public int top() {if(que1.isEmpty()){int size = que2.size();for(int i = 0;i<size-1;i++){que1.offer(que2.poll());}int ret =que2.poll();que1.offer(ret);return ret;}else{int size = que1.size();for(int i = 0;i<size-1;i++){que2.offer(que1.poll());}int ret =que1.poll();que2.offer(ret);return ret;}}public boolean empty() {return  que2.isEmpty()&&que1.isEmpty();}
}

栈实现队列

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 stack2.isEmpty()&&stack1.isEmpty();}
}

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

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

相关文章

Springboot整合JUnit5框架

目录 第一章、在pom文件中导入依赖第二章、新建测试类第三章、新建测试方法 友情提醒: 先看文章目录&#xff0c;大致了解文章知识点结构&#xff0c;点击文章目录可直接跳转到文章指定位置。 第一章、在pom文件中导入依赖 SpringBoot2.2x之后的版本中spring-boot-starter-te…

【leetcode热题100】柱状图中最大的矩形

难度&#xff1a; 困难通过率&#xff1a; 29.6%题目链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 题目描述 给定 n 个非负整数&#xff0c;用来表示柱状图中各个柱子的高度。每个柱子彼此相邻&#xff0c;且宽度为 1 。 求在该…

《学成在线》微服务实战项目实操笔记系列(P1~P83)【上】

史上最详细《学成在线》项目实操笔记系列【上】&#xff0c;跟视频的每一P对应&#xff0c;全系列12万字&#xff0c;涵盖详细步骤与问题的解决方案。如果你操作到某一步卡壳&#xff0c;参考这篇&#xff0c;相信会带给你极大启发。 一、前期准备 1.1 项目介绍 P2 To C面向…

[word] word表格表头怎么取消重复出现? #媒体#笔记#职场发展

word表格表头怎么取消重复出现&#xff1f; word表格表头怎么取消重复出现&#xff1f;在Word中的表格如果过长的话&#xff0c;会跨行显示在另一页&#xff0c;如果想要在其它页面上也显示表头&#xff0c;更直观的查看数据。难道要一个个复制表头吗&#xff1f;当然不是&…

代码随想录算法训练营day14||二叉树part01、理论基础、递归遍历、迭代遍历、统一迭代

递归遍历 &#xff08;必须掌握&#xff09; 本篇将介绍前后中序的递归写法&#xff0c;一些同学可能会感觉很简单&#xff0c;其实不然&#xff0c;我们要通过简单题目把方法论确定下来&#xff0c;有了方法论&#xff0c;后面才能应付复杂的递归。 这里帮助大家确定下来递归…

2024年最新IntelliJ IDEA:新特性与免费激活技巧

大家好&#xff0c;我是小黑&#xff0c;在如今这个信息化的时代&#xff0c;软件工程师们势必需要一款极致高效且功能全面的开发工具来提升他们的编码体验。在众多的IDE&#xff08;集成开发环境&#xff09;中&#xff0c;IntelliJ IDEA无疑以其强大的功能和易用性&#xff0…

解密输入输出迷局:蓝桥杯与ACM中C++/C语言常见问题揭秘

关于C中的常见输入输出汇总 带空格的字符串&#xff1a; ​ 对于这种输入方式我们选择使用gets() 函数来进行输入&#xff0c;gets用于从标准输入&#xff08;通常是键盘&#xff09;读取一行文本并将其存储为字符串&#xff0c;直到遇到换行符&#xff08;‘\n’&#xff09…

Ondo宣布将其原生稳定币USDY带入Sui生态

重要提示&#xff1a;USDY是由短期美国国债支持的token化票据&#xff0c;持有者享受稳定币的实用性同时获得收益。USDY不得在美国或向美国人出售或以其他方式提供。USDY也未根据1933年美国证券法注册。 不到一年的时间&#xff0c;Sui已经成为全链TVL排名前十的区块链&#xf…

使用 WPF + Chrome 内核实现高稳定性的在线客服系统复合应用程序

对于在线客服与营销系统&#xff0c;客服端指的是后台提供服务的客服或营销人员&#xff0c;他们使用客服程序在后台观察网站的被访情况&#xff0c;开展营销活动或提供客户服务。在本篇文章中&#xff0c;我将详细介绍如何通过 WPF Chrome 内核的方式实现复合客服端应用程序。…

360 安全浏览器 - 页面布局 - 常用网址

360 安全浏览器 - 页面布局 - 常用网址 自定义样式 let myStyle {https://www.baidu.com/: {color: #001483,backgroundColor: #FFF,icon: https://www.baidu.com/favicon.ico},https://blog.csdn.net/jx520: {backgroundColor: #fc5531,icon: https://g.csdnimg.cn/static/l…

软件测试工程师——缺陷(一篇足以)

目录 定义 缺陷的类型 缺陷的严重程度 缺陷的状态 缺陷的根源 ​缺陷的来源 缺陷的起源 缺陷的生命周期 缺陷的识别 缺陷报告模板 编写缺陷报告的目的 缺陷报告编写的准则 缺陷描述的准则 定义 1. 软件未实现产品说明书中所提及的功能 2. 软件实现了产品说明书中…

嵌入式学习之Linux入门篇笔记——9,Linux权限管理

配套视频学习链接&#xff1a;http://【【北京迅为】嵌入式学习之Linux入门篇】 https://www.bilibili.com/video/BV1M7411m7wT/?p4&share_sourcecopy_web&vd_sourcea0ef2c4953d33a9260910aaea45eaec8 1.为什么要管理 Linux 权限&#xff1f; 很好管理每个用户。控制每…