数据结构与算法(七)--使用链表实现栈
一、前言
之前我们已经学习了链表的所有操作及其时间复杂度分析,我们可以了解到对于链表头的相关操作基本都是O(1)的,例如链表头增加、删除元素,查询元素等等。那我们其实有一个数据结构其实可以完美利用到这些操作的特点,都是在某一段进行操作,那就是栈。本章我们通过链表去实现栈。并且比较用数组实现和用链表实现他们之间的差异。
二、用链表实现栈
2.1、代码实现
那么通过链表实现栈就很简单了,我们知道入栈和出栈都是从链表的同一端进行操作,那么我们只需调用链表的addFirst/removeFirst的方法即可,查找同理。
首先我们将链表栈命名为LinkedListStack,并且实现我们Stack的抽象类,然后设置一个内部属性为我们之前实现的链表,通过该链表完成实现需要重写的方法即可,代码如下:
public class LinkedListStack<T> implements Stack<T> {private LinkedList<T> linkedList;public LinkedListStack() {this.linkedList = new LinkedList<>();}@Overridepublic int getSize() {return linkedList.getSize();}@Overridepublic boolean isEmpty() {return linkedList.isEmpty();}@Overridepublic void push(T t) {linkedList.addFirst(t);}@Overridepublic T pop() {return linkedList.removeFirst();}@Overridepublic T peek() {return linkedList.getFirst();}@Overridepublic String toString() {StringBuilder stringBuilder = new StringBuilder();stringBuilder.append("Stack: top ");stringBuilder.append(linkedList);return stringBuilder.toString();}
}
测试一下:
public static void main(String[] args) {LinkedListStack<Integer> integerArrayStack = new LinkedListStack<>();for (int i = 0; i < 5; i++) {integerArrayStack.push(i);System.out.println(integerArrayStack);}integerArrayStack.pop();System.out.println(integerArrayStack);}
结果没有问题,通过链表实现栈就这样简单的实现了。
2.2、和数组栈比较性能
这个代码和之前数组队列和循环队列效率的对比很接近:
public class TestStackCompare {private static double testQueue(Stack<Integer> s, int opCount){long startTime = System.currentTimeMillis();Random random = new Random();for (int i = 0; i < opCount; i++) {s.push(random.nextInt(Integer.MAX_VALUE));}for (int i = 0; i < opCount; i++) {s.pop();}long endTime = System.currentTimeMillis();return (endTime - startTime)/1000.0;}public static void main(String[] args) {ArrayStack<Integer> integerArrayStack = new ArrayStack<>();LinkedListStack<Integer> integerLinkedListStack = new LinkedListStack<>();System.out.println("arrayStack,time:"+testQueue(integerArrayStack,1000000)+"s");System.out.println("linkedListStack,time:"+testQueue(integerLinkedListStack,1000000)+"s");}
}
那么我们运行下,发现两者效率近乎一致:
当然也有可能得到的结果是有差距的,对于arrayStack来说,时不时就需要扩容,这个对于某些操作系统来说比较耗费时间,而对于linkedListStack来说,它每次new Node就需要不断的开辟空间,这个操作又对于某些操作系统来说更耗费时间;而且这两者的差距会随着操作次数的增多不断拉大,因为扩容并不是每次扩容,而new Node确实是需要每次都new一个,例如我将操作次数放大为10000000次,这个时候两者的时间差距就比较大了:
所以仍然取决于你测试使用的操作系统,配置,jvm版本等等。但是其实我想强调的是,对于数组栈和链表栈来说,他们的各项操作的时间复杂度其实是一致的。他们之间没有复杂度之间的巨大差异。不像数组队列和循环队列,一个6s,一个0.01s,这之间的差距是非常大的。
相关文章:

数据结构与算法(七)--使用链表实现栈
一、前言 之前我们已经学习了链表的所有操作及其时间复杂度分析,我们可以了解到对于链表头的相关操作基本都是O(1)的,例如链表头增加、删除元素,查询元素等等。那我们其实有一个数据结构其实可以完美利用到这些操作的特点,都是在…...

分布式事务详解
摘要 分布式事务主要包括2pc、3pc、消息事务。 2pc指两阶段提交: 第一阶段是准备阶段:所有事务参与者检查执行能力并锁定对应资源,准备完成后将状态告知协调者。第二集段是提交状态:事务参与者全部准备好后,协调者发…...

车载通信架构 —— DDS协议介绍
车载通信架构 —— DDS协议介绍 我是穿拖鞋的汉子,魔都中坚持长期主义的汽车电子工程师。 老规矩,分享一段喜欢的文字,避免自己成为高知识低文化的工程师: 屏蔽力是信息过载时代一个人的特殊竞争力,任何消耗你的人和…...

nginx根据不同的客户端设备进行转发请求——筑梦之路
这里主要介绍七层负载方式实现。 环境说明: pc端 web-1 苹果ios端 web-2 安卓Android端 web-3 负载均衡 web-lb 配置示例: pc端: server {listen 9000; #监听9000server_name pc.xxx.com;charset utf-8;location / {root /…...

增强LLM:使用搜索引擎缓解大模型幻觉问题
论文题目:FRESHLLMS:REFRESHING LARGE LANGUAGE MODELS WITH SEARCH ENGINE AUGMENTATION 论文地址:https://arxiv.org/pdf/2310.03214.pdf 论文由Google、University of Massachusetts Amherst、OpenAI联合发布。 大部分大语言模型只会训练一次&#…...

WPF向Avalonia迁移(一、一些通用迁移项目)
通用变更 WPF:Visibility 其他参考文档 WPF: <TextBlock Visibility"Visible"/><TextBlock Visibility"Collapsed"/><TextBlock Visibility"Hidden"/>Avalonia : <TextBlock IsVisib…...

lua学习笔记
单行注释: 多行注释: 命名: Lua不支持下划线大写字母,比如:_ABC 但支持:_abc 关键字: 全局变量: 直接变量名 内容就是全局 局部变量: 加上local即可 nil࿱…...

修改 ModelScope 默认缓存路径
修改 ModelScope 默认缓存路径 设置 MODELSCOPE_CACHE 和 MODELSCOPE_MODULES_CACHE 两个环境变量。 export MODELSCOPE_CACHE<your_favourite_path>/hub export MODELSCOPE_MODULES_CACHE<your_favourite_path>/modelscope_modules完结!...

【ES实战】索引别名的使用说明
索引别名 文章目录 索引别名带有过滤器的别名RoutingWrite Index REST单一添加一个别名示例: 索引创建是增加别名删除别名检索现有别名示例: 索引别名可以通过API的方式进行操作一个索引别名可以映射到一个或一个以上的索引索引名和索引别名不能重复,在集群中都是唯…...

QT信号与槽机制 和 常用控件介绍
QT信号与槽机制 1、信号(signal): 所谓信号槽 (观察者模式)信号本质是事件。信号展现方式就是函数。当某一个事件发生之后,则发出一个信号(signal). 2、槽(slot): 就是对信号响应的函数,槽就是一个函数。槽函数与普通函数区别槽函数可以与一个信号关联&…...

【css-banner图片自适应】
<picture><source media"(max-width: 480px)" srcset"图片地址"><source media"(min-width: 481px)" srcset"图片地址"><img src"图片地址" id"homebanner"></picture>img{height:…...

【k8s管理操作】
k8s管理操作 一、k8s管理操作1.陈述式资源管理2.声明式资源管理 二、k8s基础信息常看(命令)增删改查项目的生命周期:创建-->发布-->更新-->回滚-->删除 headless clusterIP 无头模式 金丝雀发布(Canary Release&#…...

【java基础学习】之DOS命令
#java基础学习 1.常用的DOS命令: dir:列出当前目录下的文件以及文件夹 md: 创建目录 rd:删除目录cd:进入指定目录 cd.. :退回到上级目录 cd\ : 退回到根目录 del:删除文件 exit:退出dos命令行 1.dir:列出当前目录下的文件以及文件夹 2.md: 创建目录 …...

学习记录——StyleGAN2+SA-UNet
SA-UNet for Retinal Vessel improvment using StyleGAN2 作者提出了一种改进视网膜图像分割的方法,通过创建图像及其相应的分割地图来实现。作者的解决方案包括使用DRIVE数据集1对StylGAN2进行训练,并使用目前在分割DRIVE图像方面取得最先进结果的SA-UNet模型对新合成的图像…...

JVM222
文章目录 JVM222运行时数据区的内部结构线程程序计数器(PC寄存器)虚拟机栈 JVM222 运行时数据区的内部结构 概述 本节主要讲的是运行时数据区,也就是下图这部分,它是在类加载器加载完成后的阶段,如下图: …...

C语言 指针
含义 从根本上看,指针是一个值为内存地址的变量(或数据对象)。指针变量的值是地址。 要创建指针变量,先要声明指针变量的类型 作用 1.实现复杂的数据结构,例如数组、链表、队列和堆栈等; 2.能方便地表…...

YOLOv8血细胞检测(7):小目标大目标一网打尽,轻骨干重Neck的轻量级GFPN | 阿里ICLR2022 GiraffeDet
💡💡💡本文改进:小目标大目标一网打尽GFPN,提升大小目标检测性能 GFPN | 亲测在血细胞检测项目中涨点,map@0.5 从原始0.895提升至0.904 收录专栏: 💡💡💡YOLO医学影像检测:http://t.csdnimg.cn/N4zBP ✨✨✨实战医学影像检测项目,通过创新点验证涨点可…...

广度优先(BFS)(例子:迷宫)
广度优先搜索算法(BFS)是一种用于图形和树数据结构的搜索算法。该算法从根节点开始搜索,然后依次访问每个相邻节点。在搜索过程中,每个节点都标记为已访问,以避免重复访问。BFS算法适用于寻找最短路径的问题࿰…...

【安卓源码】安卓Watchdog 机制
在Android系统中,也设计了一个软件层面Watchdog,用于保护一些重要的系统服务,比如:AMS、WMS、PMS等,由于以上核心服务运行在system_server进程里面,所以当以上服务出现异常时,通常会将system_se…...

inscode连接不上gpu,持续8小时,为了数据不丢失续费了6小时,我只想知道什么时候可以连接
并且给我相应的补偿...

QT位置相关函数
Qt(Qt Framework)是一个流行的C应用程序开发框架,提供了丰富的位置相关函数和类,用于处理窗口、窗口小部件和图形的位置和几何操作。以下是一些常用的Qt位置相关函数和类: QPoint:QPoint类表示一个二维点的…...

vulnhub靶场 Kioptrix-level-1
简介: vulnhub是一个提供靶场环境的平台。而Kioptrix-level-1就是一个对新手比较友好的靶场。初学渗透的同学可以做做试试看,项目地址如下。 项目地址:Kioptrix: Level 1 (#1) ~ VulnHub 信息收集 查看本机IP,靶机跟kali都是使用…...

全网最细,真实企业性能测试落地实施,一文带你快速打通...
目录:导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结(尾部小惊喜) 前言 1、什么是性能测试…...

三十一、【进阶】B+树的演变过程
1、B树简单介绍 (1)介绍:B树也属于B树,是B树的变种 (2)特点:所有的数据都位于叶子节点上,叶子节点上的所有元素形成了一个单项链表 (3)图示: 2…...

算法通过村第十三关-术数|白银笔记|术数高频问题
文章目录 前言数组实现加法专题数组实现整数加法字符串加法二进制加法 幂运算专题求2的次幂求3的次幂求4的次幂 总结 前言 提示:人心本易趋死寂,苦难之后,焕然重建,激荡一阵,又趋麻木。 --苏枕书《有鹿来》 我们继续看…...

Java 线程的生命周期
🙈作者简介:练习时长两年半的Java up主 🙉个人主页:程序员老茶 🙊 ps:点赞👍是免费的,却可以让写博客的作者开兴好久好久😎 📚系列专栏:Java全栈,…...

Vue页面监听键盘按键的多种方法
在Vue页面中,可以使用多种方法来监听键盘按键。以下是至少五种常用的方法: 使用keydown或keyup指令来绑定键盘按键事件。 <template><div><input type"text" keydown.enter"handleEnterKey" /></div> <…...

解析硬件连通性测试的重要性及测试方法
在现代科技世界中,硬件设备的复杂性和多样性已经达到了前所未有的水平。无论是计算机、智能手机、物联网设备还是嵌入式系统,各种硬件组件的协同工作对于设备的正常运行至关重要。硬件连通性测试是确保这些组件相互配合无误的重要步骤。 一、硬件连通性测…...

Hive窗口函数回顾
1.语法 1.1 基于行的窗口函数 Hive的窗口函数分为两种类型,一种是基于行的窗口函数,即将某个字段的多行限定为一个范围,对范围内的字段值进行计算,最后将形成的字段拼接在该表上。 注意:在进行窗口函数计算之前&#…...

flink自定义窗口分配器
背景 我们知道处理常用的滑动窗口分配器,滚动窗口分配器,全局窗口分配器,会话窗口分配器外,我们可以实现自己的自定义窗口分配器,以实现我们的自己的窗口逻辑 自定义窗口分配器的实现 package wikiedits.assigner;i…...