Java 栈与队列超详细分析讲解
作者:Scintillator. 发布时间:2023-08-15 01:09:07
一、栈(Stack)
1、什么是栈?
栈其实就是一种数据结构 - 先进后出(先入栈的数据后出来,最先入栈的数据会被压入栈底)
什么是java虚拟机栈?
java虚拟机栈只是JVM当中的一块内存,该内存一般用来存放 例如:局部变量当调用函数时,我们会为函数开辟一块内存,叫做 栈帧,在 java虚拟机栈中开辟,具体如下。
常见考点:不可能的出栈顺序
这道题该怎么分析呢?
首先我们知道,出栈时拿到的第一个元素为4,那么4必须入栈,因为入栈的顺序是 1 2 3 4 5 6,所以4要入栈,1 2 3 得先入栈。(通过后面分析得知,该出栈序列正确)
2、栈的常见方法
方法 | 作用 |
---|---|
E push(E item) | 放入元素 |
E pop() | 获取栈顶元素并弹出 |
E peek() | 获取栈顶元素 |
boolean isEmpty() | 判断栈是否为空(父类Vector的方法) |
3、自己实现一个栈(底层用一个数组实现)
public class MyStack {
public int[] elem;
public int usedSize;
public MyStack() {
this.elem = new int[4];
}
// 放入元素
public void push(int val) {
if(isFull()) {
// 如果放满了,二倍扩容
this.elem = Arrays.copyOf(elem,2 * elem.length);
}
this.elem[this.usedSize++] = val;
}
// 获取栈顶元素并弹出
public int pop() {
if (isEmpty()) {
throw new RuntimeException("栈为空!");
}
usedSize--;
return elem[usedSize];
}
// 获取栈顶元素
public int peek() {
if (isEmpty()) {
throw new RuntimeException("栈为空!");
}
return elem[usedSize-1];
}
// 是否为空
public boolean isEmpty() {
return usedSize == 0;
}
// 是否满了
public boolean isFull() {
return elem.length == usedSize;
}
}
二、队列(Queue)
1、什么是队列?
只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有 - 先进先出。
入队列:进行插入操作的一端称为队尾
出队列:进行删除操作的一端称为队头
2、队列的常见方法
// 普通队列
Queue<Integer> queue = new LinkedList<>();
queue.offer(1);// 队尾入
int top = queue.peek();// 获取队头元素
queue.poll();// 弹出队尾元素并返回
// 双端队列
Deque<Integer> deque = new LinkedList<>();
deque.offer(1);// 默认队尾入
deque.offerFirst(2);// 队头入
deque.offerLast(3);// 队尾入
deque.peekFirst();// 获取队头元素
deque.peekLast();// 获取队尾元素
deque.pollFirst();// 弹出队头元素并返回
deque.pollLast();// 弹出队尾元素并返回
3、队列的实现(单链表实现)
/**
* 每个节点
*/
class Node{
public int val;
public Node next;
public Node(int val) {
this.val = val;
}
}
public class MyQueue {
public Node head;
public Node tail;
/**
* 插入元素 -- 尾插法
* @param val
*/
public void offer(int val) {
Node node = new Node(val);
if (head == null) {
head = node;
tail = node;
}else {
tail.next = node;
tail = tail.next;
}
}
/**
* 出队列
*/
public int poll() {
if(isEmpty()) {
throw new RuntimeException("队列为空!");
}
int val = head.val;
head = head.next;
return val;
}
/**
* 获取队头元素
*/
public int peek() {
if(isEmpty()) {
throw new RuntimeException("队列为空!");
}
return head.val;
}
// 队列是否为空
public boolean isEmpty() {
return head == null;
}
}
4、循环队列
当考虑用数组来实现一个队列, 很容易想到以下结构:
当我们连续从该队头中弹出元素时,就可以发现问题了
可以看到此时数组并没有满,但是当我们再次插入元素时,队尾却插入不了了,这时候我们可以想到将该数组看成是循环的数组,结构如下。
可以看出,当 front 和 rear 相遇时,队列可能的情况有两种,要么为空,要么是满的状态。那么队列什么时候为空,什么时候是满的呢?
我们有两种方法:
1、设置usedSize 当usedSize和数组长度相等时为满,等于0 则为空。
2、设置标志位 设 flag = true,每放一个元素,将 flag 置为 false,每有一个元素出队列,则将 flag 置为 true。当 front 和 rear 相遇时,flag为 true 则是空的,反之则是满的。
public class MyCircularQueue {
public int[] elem;
public int front;// 队头下标
public int rear;// 队尾下标
boolean flag = true;// 是否为空
public MyCircularQueue(int k) {
elem = new int[k];
}
// 向循环队列插入一个元素。如果成功插入则返回真。
public boolean enQueue(int value) {
if (isFull()) {
return false;
// throw new RuntimeException("队列已满!");
}
elem[rear] = value;
rear = (rear + 1) % elem.length;
flag = false;
return true;
}
// 从循环队列中删除一个元素。如果成功删除则返回真。
public boolean deQueue() {
if (isEmpty()) {
return false;
// throw new RuntimeException("队列为空!");
}
front = (front + 1) % elem.length;
flag = true;
return true;
}
// 从队首获取元素。如果队列为空,返回 -1 。
public int Front() {
if (isEmpty()) {
return -1;
// throw new RuntimeException("队列为空!");
}
return elem[front];
}
// 获取队尾元素。如果队列为空,返回 -1 。
public int Rear() {
if (isEmpty()) {
return -1;
// throw new RuntimeException("队列为空!");
}
// 如果是0下标,拿最后一个元素
if (rear == 0) {
return elem[elem.length-1];
}else {
return elem[rear - 1];
}
}
// 检查循环队列是否为空。
public boolean isEmpty() {
if (rear == front && flag){
return true;
}
return false;
}
// 检查循环队列是否已满。
public boolean isFull() {
if (rear == front && !flag){
return true;
}
return false;
}
}
来源:https://blog.csdn.net/qq_45792749/article/details/123811021
猜你喜欢
- 本文实例讲述了Java Web项目部署在Tomcat运行出错与解决方法。分享给大家供大家参考,具体如下:1、在部署Java Web项目的过程
- 概述在移动应用开发中,消息推送可以说是一项非常重要的功能,它能够起到提醒或者唤醒用户的作用,同时也是产品运营人员更高效地实现运营目标的重要手
- 自从SEOTcs系统11月份24日更新了一下SEO得分算法以来,一直困扰我的一个问题出现了,java的数据job任务,在执行过程中会经常报以
- 这篇文章主要介绍了java多线程加锁以及Condition类的使用实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参
- 本文实例为大家分享了Android绝对布局AbsoluteLayout的具体代码,供大家参考,具体内容如下1>AbsoluteLayo
- 图像滤波在opencv中可以有多种实现形式自定义滤波如使用3×3的掩模:对图像进行处理.使用函数filter2D()实现#include&l
- 前言我们在学习Windows应用程序开发中,经常会用到消息对话框给用户或者管理员一些的消息提示,它们都是基于对MessageBox类的消息对
- 准备:wildfly/tomcat或者其他服务器你的数据库的Driver,(此处用的mysql-connecter-java-5.1.39-
- 前言之前用简书的时候一直是在web端,后来下载了客户端,看到了搜索的那个动画,就尝试的去写了,没写之前感觉挺容易的,写了之后,就感觉里面还是
- 前言这里主要简单介绍如何使用Camera+SurfaceView自定义相机拍照,如果是Camera2或者是TextureView的可以前往主
- Android四种数据存储的应用方式作为一个完整的应用程序,数据存储操作是必不可少的。因此,Android系统一共提供了四种数据存储方式。分
- 最新开发新项目的时候,要做分享项目,要求分享有微信,微信朋友圈,QQ,QQ空间,新浪微博这五个,所分享内容包括,分享纯图片,纯文字,图文类型
- 仅供学习交流,禁止商业用途。如侵害利益,联系必删!前言最近一位小伙伴钟爱二次元文化,于是找到半次元这个app,但是很快他就遇到了问题。一、案
- 上篇介绍了几种图表的公共组件X、Y轴、背景Board的绘制。这章节介绍柱状图表的绘制,相对其它图表而言简单一些,这里主要介绍图表主体的绘制,
- 一 :问题背景问题:当查询接口较复杂时候,数据的获取都需要[远程调用],必然需要花费更多的时间。 假如查询文章详情页面,需要如下标注的时间才
- 环境:VS2019+Qt5.121. CLR库安装 &nb
- 一、系统介绍1.开发环境开发工具:Eclipse2021JDK版本:jdk1.8Mysql版本:8.0.132.技术选型Java+Swing
- 逆时针画圆弧,原理:将360度分割成36份,分别标出每10度角度时的坐标点,然后将每个点连接起来。 #include <io
- Java实现PC微信扫码支付做一个电商网站支付功能必不可少,那我们今天就来盘一盘微信支付。微信支付官方网站业务流程:开发指引文档支付服务开发
- 序言小编在项目中有遇到使用 flutter 实现扫码枪接入的需求。为方便使用,小编把能力封装成 package 并发布。好记性不如烂笔头,下