StackQueue+泛型简单理解

  • 🍁 个人主页:爱编程的Tom
  • 💫 本篇博文收录专栏:Java专栏
  • 👉 目前其它专栏:c系列小游戏     c语言系列--万物的开始_               
  • 🎉 欢迎 👍点赞✍评论⭐收藏💖三连支持一下博主🤞
  • 🧨现在的沉淀就是对未来的铺垫🎨 

目录

前言

栈(Stack)

栈的定义

栈的使用 

栈的模拟实现 

栈的应用场景

改变元素的序列  

将递归转化为循环 

队列(Queue) 

队列的定义 

队列的使用 

队列模拟实现 

循环队列 

双端队列 (Deque) 

泛型



 

前言

本篇文章将带你深入了解栈和队列的底层知识和基础架构,学会使用对数据的组织和运用!

栈(Stack)

栈的定义

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作

进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。

栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。  

压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶

出栈:栈的删除操作叫做出栈。出数据在栈顶

下面结合图片给出具体的理解:

 

栈的使用 

 

下面给出代码的运用加以理解: 

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

栈的模拟实现 

 

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

Stack的具体模拟实现如下: 

public class MyStack {public int[] elem;public int usedSize;public static final int DEFAULT_CAPACITY = 10;public MyStack() {this.elem = new int[DEFAULT_CAPACITY];}//压栈public void push(int val) {if (isFull()) {this.elem = Arrays.copyOf(elem,2*elem.length);}elem[usedSize++] = val;}public boolean isFull() {return usedSize == elem.length;}//出栈public int pop() {if (isEmpty()) {throw new EmptyStackException("栈为空!!!!");}int oldVal = elem[usedSize-1];usedSize--;//elem[usedSize] = null;return oldVal;}public boolean isEmpty() {return usedSize == 0;}public int peek() {if(isEmpty()) {throw new EmptyStackException("栈为空!!!!!");}return elem[usedSize - 1];}
}

栈的应用场景

改变元素的序列  

如上图两题在栈的理解上,解决可得选项为 C 和 B.

将递归转化为循环 

这里给大家提供一个例子:逆序打印链表 

// 递归方式
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 + " ");}
}

这里还有一些练习的题目:如果想更深入了解栈的相关机理,可以尝试做一做

1.括号匹配

2.逆波兰表达式 

3.出栈入栈次序匹配 

4.最小栈 

这里提出一个思考题:栈、虚拟机栈、栈帧有什么区别呢?

:栈是一种数据结构,具有后进先出(LIFO)的特性,用于存储函数调用、局部变量等数据。在计算机中,栈通常是指操作系统管理的内存区域,用于存储函数调用时的参数、返回地址、局部变量等。

虚拟机栈:虚拟机栈是指在Java虚拟机中用来执行Java方法的内存区域,用于存储方法的局部变量、操作数栈、动态链接、方法出口等信息。虚拟机栈与操作系统的栈类似,但是在Java虚拟机中,每个线程都有自己的虚拟机栈,用于执行方法时的数据存储。

栈帧:栈帧是指在方法调用时压入虚拟机栈中的数据结构,用于存储方法的局部变量、操作数栈、动态链接、方法出口等信息。每个方法调用都会创建一个对应的栈帧,用于存储该方法执行时需要的数据。栈帧是虚拟机栈中的一个重要组成部分,用于支持方法的执行和调用。

队列(Queue) 

队列的定义 

队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,

队列具有先进先出FIFO(First In First Out)

入队列:进行插入操作的一端称为队尾(Tail/Rear)

出队列:进行删除操作的一端称为队头 (Head/Front)  

 

队列的使用 

在Java中,Queue是个接口,底层是通过链表实现的。  

 

注意:

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

队列模拟实现 

队列中既然可以存储元素,那底层肯定要有能够保存元素的空间

常见的空间类型有两种:顺序结构 和 链式结构。

思考题:队列的实现使用顺序结构还是链式结构好? 

顺序结构:

优点:顺序结构的队列使用数组实现,插入和删除操作的时间复杂度为O(1),在空间上比较节省。

缺点:在插入和删除元素时,需要移动其他元素,可能会导致性能下降。而且顺序结构的队列有容量限制,当队列满时需要进行扩容操作。

链式结构:

优点:链式结构的队列使用链表实现,插入和删除操作的时间复杂度为O(1),不需要移动其他元素。而且链式结构的队列没有容量限制,可以动态增加或减少元素。

缺点:链式结构的队列在内存占用上比顺序结构更大,因为每个节点都需要额外的指针指向下一个节点。

总结:如果对内存占用要求比较高,且队列的大小是固定的,可以选择顺序结构实现队列;如果对插入和删除操作的性能要求比较高,且队列的大小是动态变化的,可以选择链式结构实现队列。

队列实现场景图:

 

下面给出模拟实现的代码(仅供参考): 

public class Queue {// 双向链表节点public static class ListNode{ListNode next;ListNode prev;int value;ListNode(int value){this.value = value;}}ListNode first;   // 队头ListNode last;    // 队尾int size = 0;// 入队列---向双向链表位置插入新节点public void offer(int e){ListNode newNode = new ListNode(e);if(first == null){first = newNode;// last = newNode;}else{last.next = newNode;newNode.prev = last;// last = newNode;}last = newNode;size++;}// 出队列---将双向链表第一个节点删除掉public int poll(){// 1. 队列为空// 2. 队列中只有一个元素----链表中只有一个节点---直接删除// 3. 队列中有多个元素---链表中有多个节点----将第一个节点删除int value = 0;if(first == null){return null;}else if(first == last){last = null;first = null;}else{value = first.value;first = first.next;first.prev.next = null;first.prev = null;}--size;return value;}// 获取队头元素---获取链表中第一个节点的值域public int peek(){if(first == null){return null;}return first.value;}public int size() {return size;}public boolean isEmpty(){return first == null;}
}

循环队列 

 

数组下标循环的小技巧

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 stack = new ArrayDeque<>();//双端队列的线性实现

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

泛型

泛型:就是适用于许多许多类型。从代码上讲,就是对类型实现了参数化。 

主要目的:就是指定当前的容器,要持有什么类型的对象。让编译器去做检查。 

在编译的过程当中,将所有的T替换为Object这种机制,这种机制称为:擦除机制。  

class MyArray<T> {public T[] array = (T[])new Object[10];//1public T getPos(int pos) {return this.array[pos];}public void setVal(int pos,T val) {this.array[pos] = val;}
}
public class TestDemo {public static void main(String[] args) {MyArray<Integer> myArray = new MyArray<>();//2myArray.setVal(0,10);myArray.setVal(1,12);int ret = myArray.getPos(1);//3System.out.println(ret);myArray.setVal(2,"bit");//4}
}

对上述代码进行一个说明:

1. 类名后的代表占位符,表示当前类是一个泛型类

了解:【规范】类型形参一般使用一个大写字母表示,

常用的名称有:

E 表示 Element

K 表示 Key

V 表示 Value

N 表示 Number

T 表示 Type

S, U, V 等等 - 第二、第三、第四个类型

2. 注释1处,不能new泛型类型的数组 ,说明:

T[] ts = new T[5];//是不对的

3. 注释2处,类型后加入 指定当前类型

4. 注释3处,不需要进行强制类型转换

5. 注释4处,代码编译报错,此时因为在注释2处指定类当前的类型,此时在注释4处,编译器会在存放元素的时 候帮助我们进行类型检查。

此处只对泛型做一个简单的介绍,不作过多解释,理解就好......  

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

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

相关文章

LeetCode2215找出两数组的不同

题目描述 给你两个下标从 0 开始的整数数组 nums1 和 nums2 &#xff0c;请你返回一个长度为 2 的列表 answer &#xff0c;其中&#xff1a;answer[0] 是 nums1 中所有 不 存在于 nums2 中的 不同 整数组成的列表。answer[1] 是 nums2 中所有 不 存在于 nums1 中的 不同 整数组…

Autosar架构

蓝框那种叫component&#xff0c;绿框的叫function cluster。 接口 有三种接口&#xff0c;RTE跟SWC之间链接的叫Autosar Interface&#xff0c;RTE跟BSW的Components链接是Standardized Interface&#xff0c;RTE跟BSW的services链接的是Standardized Autosar Interface。 St…

网络协议的分类

1.概要 网络协议可以分为三类&#xff1a; 封装协议路由协议功能类协议 2.分类说明 OSPF报文直接调用_ IP协议__协议进行封装&#xff0c;以目的地址_244.0.0.5 __发送到所有的OSPF路由器? 244.0.0.1 所有主机&#xff1b;244.0.0.2 所有路由器&#xff1b;244.0.0.6 指定…

Vue+springboot的批量删除功能

vue前台 <div style"margin-bottom: 10px"><el-button type"primary" plain click"handleAdd">新增</el-button><el-button click"delBatch" type"danger" plain style"margin-left: 5px"…

C语言例题41、八进制转换为十进制

#include<stdio.h>void main() {int x;printf("请输入一个8进制整数&#xff1a;");scanf("%o", &x);printf("转换成十进制后的整数为%d\n", x); }运行结果&#xff1a; 本章C语言经典例题合集&#xff1a;http://t.csdnimg.cn/FK0Qg…

Java入门基础学习笔记21——Scanner

在程序中接收用户通过键盘输入的数据&#xff1a; 需求&#xff1a; 请在程序中&#xff0c;提示用户通过键盘输入自己的姓名、年龄、并能在程序中收到这些信息&#xff0c;怎么解决&#xff1f; Java已经写好了实现程序&#xff0c;我们调用即可。 API&#xff1a;Applicat…

2024 年中国大学生程序设计竞赛全国邀请赛(郑州)暨第六届CCPC河南省大学生程序设计竞赛 problem K. 树上问题

//先找一个美丽的树&#xff0c;然后遍历树找节点,分析是否符合条件。 //画几个图&#xff0c;思考下。 #include<bits/stdc.h> using namespace std; #define int long long const int n1e611; int a,b,c[n],d,l,r,k,w,an; vector<int>t[n]; void dfs(int x,int…

什么是页分裂、页合并?

数据组织方式 在InnoDB存储引擎中&#xff0c;表数据都是根据主键顺序组织存放的&#xff0c;这种存储方式的表称为索引组织表(index organized table IOT)。 行数据&#xff0c;都是存储在聚集索引的叶子节点上的。而我们之前也讲解过InnoDB的逻辑结构图&#xff1a; 在I…

61、内蒙古工业大学、内蒙科学技术研究院:CBAM-CNN用于SSVEP - BCI的分类方法[脑机二区还是好发的]

前言&#xff1a; 之前写过一篇对CBAM模型改进的博客&#xff0c;在CBAM中引入了ECANet结构&#xff0c;对CBAM中的CAM、SAM模块逐一改进&#xff0c;并提出ECA-CBAM单链双链结构&#xff0c;我的这个小的想法已经被一些同学实现了&#xff0c;并进行了有效的验证&#xff0c;…

快速对比 找出2个名单不同之处

import pandas as pd# 读取两个Excel文件 df1 pd.read_excel(1.xlsx) df2 pd.read_excel(2.xlsx)# 检查两个DataFrame的列是否相同 if list(df1.columns) ! list(df2.columns):print("两个Excel文件的列不一致。")print("文件1的列&#xff1a;", df1.co…

AI智能体|手把手教你申请一个Kimi(Moonshot)的API KEY

大家好&#xff0c;我是无界生长。 今天分享一下如何申请一个Kimi(Moonshot)的API KEY&#xff0c;为后面Kimi(Moonshot)接入微信机器人做铺垫。学会了的话&#xff0c;欢迎分享转发&#xff01; 前提 拥有一个Kimi(Moonshot)账号 使用手机号注册即可&#xff0c;新用户可免费…

【线程创建】——三种方式➕多线程案例练习

02 线程创建 Thread , Runnable , Callable 三种创建方式 Thread class - 继承Thread类 (重点) Runnable接口 - 实现Runnable接口 (重点) Callable接口 - 实现Callable接口 (了解) Thread 类实现 它继承了老祖宗 Object java.lang.Object java.lang.Thread 它实现了 Runnab…

文本到语音的学习笔记:从Docker开始

1.docker 是什么意思&#xff1f; Docker 是一种开源的容器化平台&#xff0c;它允许开发者将应用及其依赖打包到一个轻量级、可移植的容器中&#xff0c;然后可以在任何支持Docker的系统上运行这个应用&#xff0c;而不必担心环境差异导致的问题。 以下是Docker的一些关键特…

【go项目01_学习记录11】

操作数据库 1 文章列表2 删除文章 1 文章列表 &#xff08;1&#xff09;先保证文章已经有多篇&#xff0c;可以直接在数据库中添加&#xff0c;或者访问链接: localhost:3000/articles/create&#xff0c;增加几篇文章。 &#xff08;2&#xff09;之前设置好了articles.ind…

栈队列经典OJ题(详细过程)

1. 有效的括号 - 力扣&#xff08;LeetCode&#xff09; 第一题判断有效的括号&#xff0c;这道题我们会用到栈的知识&#xff0c;栈是后进先出的&#xff0c;可以根据这个来解这道题&#xff0c;先看一下题目和示例。 1.1整体思路 我们通过示例可以看出括号匹配就返回true&am…

【JAVA】BOSS系统发版艺术:构建高效、优雅的微服务部署策略

在现代软件开发领域&#xff0c;微服务架构与容器化部署已迅速成为行业新趋势。微服务架构通过将应用拆分成多个小型、自治的服务单元&#xff0c;每个服务承担某项特定的业务功能。而容器化部署则以其轻量级和高度可移植的特性&#xff0c;为这些微服务的有效打包、分发和运行…

科技查新中的工法查新点如何确立与提炼?案例讲解!

按《工程建设工法管理办法》( 建 质&#xff3b;2014&#xff3d;103 号) &#xff0c;工法&#xff0c;是指以工程为对象&#xff0c;以工艺为核心&#xff0c;运用系 统工程原理&#xff0c;把先进技术和科学管理结合起来&#xff0c;经过一定工程实践形成的综合配套的施工方…

探索美国动态IP池:技术赋能下的网络安全新篇章

在数字化飞速发展的今天&#xff0c;网络安全成为了各行各业关注的焦点。特别是在跨国业务中&#xff0c;如何保障数据的安全传输和合规性成为了企业面临的重要挑战。美国动态IP池作为一种新兴的网络技术&#xff0c;正逐渐走进人们的视野&#xff0c;为网络安全提供新的解决方…

黑马甄选离线数仓项目day02(数据采集)

datax介绍 官网&#xff1a; https://github.com/alibaba/DataX/blob/master/introduction.md DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre…

计算机Java项目|Springboot学生读书笔记共享

作者主页&#xff1a;编程指南针 作者简介&#xff1a;Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、腾讯课堂常驻讲师 主要内容&#xff1a;Java项目、Python项目、前端项目、人工智能与大数据、简…