《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());}}
}

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

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

相关文章

DAMA学习笔记(七)-数据集成和互操作

1.引言 数据集成和互操作(DII)描述了数据在不同数据存储、应用程序和组织这三者内部和之间进行移动和整合的相关过程。数据集成是将数据整合成物理的或虚拟的一致格式。数据互操作是多个系统之间进行通信的能力。数据集成和互操作的解决方案提供了大多数组织所依赖的基本数据管…

Unity XR Interaction Toolkit设置或监听手柄按键事件(三)

提示&#xff1a;文章有错误的地方&#xff0c;还望诸位大神不吝指教&#xff01; 文章目录 前言一、XRI Default Input Actions1.导入官方案例2.设置控制器绑定&#xff0c;如手柄、主/辅助按钮、操纵杆等1.要设置控制器绑定&#xff0c;如左右手 手柄、主/辅助按钮、操纵杆等…

[k8s源码]8.deltaFIFO

deltaFIFO DeltaFIFO: 这是一个特殊类型的队列&#xff0c;它结合了FIFO&#xff08;先进先出&#xff09;队列的特性和增量&#xff08;Delta&#xff09;处理的能力。DeltaFIFO 中是按顺序存储的&#xff0c;但它们不必严格按照发生的顺序逐个处理。这种设计提供了处理的灵…

【C++中线程学习】

1、多线程 C11之前没有引入线程的概念&#xff0c;如果想要实现多线程&#xff0c;需要借助操作系统平台提供的API&#xff0c;比如Linux的<pthead.h>&#xff0c;或者windows下的<windows.h>。 C11提供了语言层面上的多线程&#xff0c;包含在头文件<thread.h…

在Windows下部署jar包,关闭命令提示符可以后台运行

前言 大多数情况下&#xff0c;都是选用Linux作为服务器部署服务&#xff0c;在Linux中通过以下命令运行 nohup java -jar xxxxx-1.0-SNAPSHOT.jar 但是有时由于其他原因&#xff0c;或本地测试&#xff0c;或云服务器使用Windows server等等&#xff0c;需要在Windows上面运…

matlab仿真 数字基带传输(下)

&#xff08;内容源自详解MATLAB&#xff0f;SIMULINK 通信系统建模与仿真 刘学勇编著第六章内容&#xff0c;有兴趣的读者请阅读原书&#xff09; clear all Fd1;%符号采样频率 Fs10;%滤波器采样频率 r0.2;%滤波器滚降系数 delay4;%滤波器时延 [num,den]rcosine(Fd,Fs,defau…

Python读取grib数据获取变量推荐姿势

前情提要 最近使用的EC和GFS预报数据给的都是grib2格式的&#xff0c;之前用惯nc格式的&#xff0c;python读取grib2数据的时候还走了些弯路&#xff0c;看到很多博客上给的教程其实不能满足我的需求&#xff0c;现在搞明白了分享一下 pygrib安装 第一个问题就是我电脑上pyg…

通信原理实验六:实验测验

实验六 实验测验 一&#xff1a;测验内容和要求 测试需要完成以下几个步骤&#xff1a; 配置好以下网络图&#xff1b;占总分10%&#xff08;缺少一个扣一分&#xff09;根据下面图配置好对应的IP和网关以及路由等相关配置&#xff0c;保证设备之间连通正常&#xff1b;占总…

领略诗词之妙,发觉生活之美。

文章目录 引言落霞与孤鹜齐飞,秋水共长天一色。野渡无人舟自横。吹灭读书灯,一身都是月。我醉欲眠卿且去,明朝有意抱琴来。赌书消得泼茶香,当时只道是寻常。月上柳梢头,人约黄昏后。最是人间留不住,朱颜辞镜花辞树。山中何事?松花酿酒,春水煎茶。似此星辰非昨夜,为谁风…

用Swagger进行后端接口测试的实战操作

目录 一.什么是Swagger&#xff1f; 二.Swagger的使用操作流程&#xff1a; 1.在pom.xml配置文件导入 Knife4j 的依赖&#xff1a; 2.在config配置类中加入 Knife4j 的相关配置并设置静态资源映射&#xff08;否则接口文档无法访问&#xff09;&#xff1a; 三.Swagger的四个…

redis构建集群时,一直Waiting for the cluster to join

redis构建集群时&#xff0c;一直Waiting for the cluster to join 前置条件参考 前置条件 这是我搭建的集群相关信息&#xff0c;三台虚拟机&#xff0c;分别是一主一从。在将所有虚拟机中redis服务器用到的tcp端口都打开之后&#xff0c;进行构建集群。但是出现上面的情况。 …

【llama3.1】ollama的使用--本地部署使用llama3.1模型

快速入门 安装完成ollama后,在命令行窗口输入 ollama run llama3 上图表示 Ollama 正在下载 llama3 任务所需的资源文件,并显示了当前的下载进度、速度和预计剩余时间。这是 Ollama 在准备运行 llama3 任务之前所需的步骤。 上面的步骤完成后,就可以在本地进行聊天了,…

基于 HTML+ECharts 实现的数据可视化大屏案例(含源码)

数据可视化大屏案例&#xff1a;基于 HTML 和 ECharts 的实现 数据可视化已成为企业决策和业务分析的重要工具。通过直观、动态的图表展示&#xff0c;数据可视化大屏能够帮助用户快速理解复杂的数据关系&#xff0c;发现潜在的业务趋势。本文将介绍如何利用 HTML 和 ECharts 实…

区块链和数据要素融合的价值及应用

一、数据要素面临的关键障碍 在构建数据要素基石的过程中&#xff0c;首要任务是明确并解决产权架构的难题&#xff0c;特别是使用权的确立与流转机制的顺畅&#xff0c;此乃数字经济蓬勃发展的命脉所在。一个高效的数据流转体系对于激发数据潜能、加速经济发展及优化数据资源…

JVM系列(三) -类加载器及双亲委派模型介绍

在之前的文章中&#xff0c;介绍了类的加载过程中&#xff0c;我们有提到在加载阶段&#xff0c;通过一个类的全限定名来获取此类的二进制字节流操作&#xff0c;其实类加载器就是用来实现这个操作的。 在虚拟机中&#xff0c;任何一个类&#xff0c;都需要由加载它的类加载器…

声音克隆一键本地化部署 GPT-SoVITS

文章目录 GPT-SoVITS 介绍1:GPT-SoVITS安装2:GPT-SoVITS使用2.1 人声伴奏分离,去混响去延时工具2.2 语音切分工具2.3 语音降噪工具2.4 中文批量离线ASR工具2.5 语音文本校对标注工具GPT-SoVITS 介绍 GPT-SoVITS: 是一个由RVC变声器创始人“花儿不哭”推出的免费开源项目。…

WPF多语言国际化,中英文切换

通过切换资源文件的形式实现中英文一键切换 在项目中新建Language文件夹&#xff0c;添加资源字典&#xff08;xaml文件&#xff09;&#xff0c;中文英文各一个。 在资源字典中写上想中英文切换的字符串&#xff0c;需要注意&#xff0c;必须指定key值&#xff0c;并且中英文…

DT浏览器首页征集收录海内外网址

DT浏览器首页征集收录海内外网址&#xff0c;要求页面整洁&#xff0c;内容丰富&#xff0c;知识性和可读性强&#xff0c;符合大众价值观&#xff0c;不含恶意代码

学术研讨 | 区块链与隐私计算领域专用硬件研讨会顺利召开

学术研讨 添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 近日&#xff0c;国家区块链技术创新中心主办&#xff0c;长安链开源社区支持的“区块链性能优化与融合技术研讨会”顺利召开。当前&#xff0c;区块链与新技术之间的交叉融合和协同创新正成为显…

springboot+webSocket对接chatgpt

webSocket对接参考 话不多说直接上代码 WebSocket package com.student.config;import com.alibaba.fastjson2.JSONArray; import com.alibaba.fastjson2.JSONObject; import lombok.extern.slf4j.Slf4j; import org.springframework.http.MediaType; import org.springfram…