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,一经查实,立即删除!

相关文章

ddpm Denoising Diffusion Probabilistic Model 学习笔记

目录 Stable Diffusion 文章的贡献抽象出来就两个 潜空间上做扩散生成 ddpm(Denoising Diffusion Probabilistic Model)学习笔记 算法原理 unet预测噪声 unet推理过程 重参数化技巧 &#xff08;1&#xff09;利用前一时刻的 xt-1 得到任意时刻的噪声图片 xt&#xff…

LeetCode2215找出两数组的不同

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

Linux poweroff命令教程:如何实现一键关机(附实例详解和注意事项)

Linux poweroff命令介绍 poweroff命令是用来关闭系统的。当你执行这个命令时&#xff0c;它会发送一个信号给系统&#xff0c;告诉系统关闭所有的进程&#xff0c;然后关闭系统。这个命令非常有用&#xff0c;特别是在你需要远程关闭系统&#xff0c;或者你的系统没有图形用户…

Autosar架构

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

项目部署到线上proxytable代理失效nginx报404的问题

我的项目是在vue的config文件夹中的index.js中配置了接口地址 &#xff0c;本地跑的时候都能访问&#xff0c;放到线上就报404&#xff1b; module.exports {dev: {// PathsassetsSubDirectory: static,assetsPublicPath: /,proxyTable: {/xxx: {target: http://xxxxxxxx:xxx…

分享四种CAD图纸加密方法,严防盗图

在数字化时代&#xff0c;cad图纸的盗用和非法传播问题日益突出。对于企业和设计师来说&#xff0c;保护设计成果的安全性和原创性&#xff0c;采取有效的cad加密方法至关重要。本文将分享四种cad加密方法&#xff0c;帮助您严防盗图&#xff0c;保护图纸安全。 使用cad软件内…

网络协议的分类

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 指定…

【前端每日一题】day5

JS 实现继承的几种方式 在JavaScript中&#xff0c;实现继承的几种方式包括原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承和组合式继承。 原型链继承&#xff1a; function Parent() {this.name Parent; } Parent.prototype.sayHello function() {console.…

当它还是幼生期的时候,及早离开它!

当我们有丰富的精神生活时&#xff0c;充实的知识吸收储备时&#xff0c;为自己的每一点进步而欣慰时&#xff0c;我们就不会有失败的忧虑。也不会有孤单的自怜。 没有人是弱者&#xff0c;每个人都有自己活着的方式&#xff0c;当你内心强大时&#xff0c;你会尊重每一个“弱者…

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"…

Spring Cloud 背后技术详解

Spring Cloud 是基于 Spring Boot 的一套微服务架构解决方案。它为开发者提供了一系列的工具&#xff0c;用于快速构建分布式系统中的一些常见模式&#xff08;例如配置管理、服务发现、断路器等&#xff09;。Spring Cloud 利用 Spring Boot 的自动配置和独立运行能力&#xf…

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基础(33)Java Web拦截器作用和用法

Java Web拦截器&#xff08;Interceptor&#xff09;是Java Web开发中一个重要的概念&#xff0c;它允许开发者在处理HTTP请求和响应之前或之后执行特定的代码&#xff0c;从而实现如权限检查、日志记录、事务管理等功能。拦截器可以作用于Java EE的Servlet、Spring框架、Strut…

redis试题按知识点归类(四)

十六、实战应用 1.如何使用 Redis 存储用户会话&#xff1f; 2.Redis 在电子商务平台中的应用是什么&#xff1f; 3.如何使用 Redis 进行实时数据分析&#xff1f; 十七、面试题综合 1.描述一次你解决 Redis 性能问题的经历。 2.你如何理解 Redis 中的“单线程”模型&…

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…

MLT剪辑sample

#include <framework/mlt.h> int main(int argc, char **argv) { // 初始化MLT mlt_factory factory mlt_factory_init(NULL); // 加载素材&#xff08;这里假设我们有一个名为"video.mp4"的视频文件&#xff09; mlt_profile profile mlt_prof…

什么是页分裂、页合并?

数据组织方式 在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…