欢迎光临Java中的客“栈”

就目前而言,相信大家对数组、链表还有栈都基本已经有了一些了解,本篇文章将以栈为主体,探究栈和数组,栈和链表之间的一些联系。

当然在开始对栈的学习之前,我们先回顾有关数组、链表的基础知识点。

学习代码就是一个不断遗忘且巩固的过程,如何让敲出来的代码在心中印象更为深刻呢?不妨为这些有规律的字母的排列组合赋予一些当下事物的灵动性。

在这里我不得不提到当下的热梗:诸如来自歌手2024中的“五旬老太守国门”、“叶赫那拉氏大战八国联军”等等,既然咱们英子在这期舞台上是那么的孤单无助,在本篇代码里我将在循环取出栈中元素时,为英子来点助力,毕竟,57岁正是拼搏的年龄,咱们英子不能输,一个不够就来俩,两个不够我就来N个,真舞台咱也上不去,那就只能在代码里为我们的歌手们呐喊助威了!(见三)

天天抖手,精神抖擞!

目录

一、链表与数组(Array and LinkedList)

1.关于数组 Array

2.关于链表 LinkedList

二、栈 (Stack)

1.泛型简介

2.什么是栈

3.数组与栈

1)栈的存与取

2)数组和栈删除之间的区别

3)代码实现

4.链表与栈

1)栈中数据的插入与删除

2)基本代码实现

3)头插法与尾插法

三、整体代码


一、链表与数组(Array and LinkedList)

1.关于数组 Array

数组在内存中是一段连续的空间,每段的编号都是从0开始的,依次递增,也称为数组的下标。

数组可以通过索引(下标)访问其任意位置的元素。

数组不能够自动扩容且长度固定不可变。

除了掌握数组的创建,还需要会使用的就是数组的存和取。

int[] array1 = new int[10];//动态初始化
int[] array2 = {1,2,3,4,5};//静态初始化

在整数型数组的动态初始化里,每个元素的初始值都为0,不同类型的数组初始值不同。

public class Test {//存public static void main(String[] args) {int[] array = new int[5];for (int i = 0; i < array.length; i++) {array[i] = i * 2 + 1;}for (int i = 0; i < array.length; i++) {System.out.println("array[" + i + "] = " + array[i]);}}
}
public class Test {//取public static void main(String[] args) {int[] arr1 = {1,2,3,4,5};for (int i = 0; i < arr1.length; i++) {System.out.print(arr1[i]+" ");}System.out.print("\n");int[] arr2 = new int[5];for (int j  = 0;j < arr2.length; j++){int value = arr2[j];System.out.print(value+" ");}}}

运行结果:

1 2 3 4 5 
0 0 0 0 0 

2.关于链表 LinkedList

这里主要回顾单向链表。链表长度可变,且可以实现自动扩容,但不能通过下标进行访问。

链表使用节点对象储存数据,节点之间相互存储地址建立连接。

链表主要几个概念:头节点和尾结点。

头节点(head): 链表的第一个节点称为头节点,通常用来表示整个链表的起始位置。

尾节点(last): 链表的最后一个节点称为尾节点,其指针通常指向 null,表示链表的结束。

但与数组不同,链表中的元素在内存中不是连续存储的,而是通过指针(引用)相互连接起来。  

图示的为链表的一个节点node,value是这个节点的所存储的数据值,next为下一节点的地址。

二、栈 (Stack)

1.泛型简介

为什么叫泛型?一般提到关于“泛”的都是联想到广泛、宽泛、空泛、泛泛之交等词语、所以不难得出泛具有适用性广、通用性强等特征。所以在Java中的泛型一般用在尚不确定的数据类型中,可以暂替多种数据类型,以下段代码为例。

public class pandora_box<T> {private T value;public void setValue(T value){this.value=value;System.out.println(value);}public T getValue(){System.out.println(value);return value;}public static void main(String[] args) {pandora_box<String> box1 = new pandora_box<>();box1.getValue();box1.setValue("潘多拉魔盒");pandora_box<Integer> box2 = new pandora_box<>();box2.setValue(111);box2.getValue();}
}

输出结果:

null
潘多拉魔盒
111
111

2.什么是栈

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

底层可以使用数组或链表进行实现。

采取先进后出(LIFO:last in first of)原则: 即先存入的数据,最后才能取出

类比:放羽毛球的盒子,最先放进去的是最后一个拿出来的,或一个单向闭口的管道(最先存入的为栈底、最后一个存入的为栈顶)。

总结:栈的操作只涉及栈顶元素,而不会涉及栈底或中间的元素。

3.数组与栈

数组可以理解成为一种固定长度的栈。

1)栈的存与取

存:按照下标正常存入

取:从最后的元素开始依次向前

2)数组和栈删除之间的区别

数组:找到对应的下标,将改下标后一位置的元素逐一向前挪一个

栈:倒着一一取出直至找到需要删除的数据

对于插入数据数据呢?会很麻烦,一旦越过最后一个要取前面的步骤就会很繁琐。

3)代码实现

Object[ ]是一个数组,其中每个元素的类型都是Object。在 Java 中,Object 是所有类的祖先,因此 Object[ ] 数组可以存储任何类型的对象,包括基本数据类型的包装类对象和用户自定义的类对象。

由于Object是所有类的直接或间接父类,因此 Object[ ] 数组可以存储任意类型的对象,例如String、Integer、Double 等。当你不确定数组中需要存储哪种类型的对象时,可以使用         Object[ ] 数组作为一种通用的容器。(类比泛型的思想)

public class ArrayStack<E> {Object[] stackArr = new Object[10];int size=0;public void add(E e){//定义了一个公有的方法 add,用于向栈中添加元素//该方法使用泛型类型 T 作为参数类型,表示可以接受任意类型的对象(即传入)if (stackArr.length==size){System.out.println("小二提示:您的客栈已满!");return;}stackArr[size++]=e; //这行代码相当于stackArr[size]=e;size++;//将传入的元素 t 添加到栈顶(数组中的下一个空位置),并将 size 自增//这里利用 size 变量来记录当前栈中元素的个数,并在添加元素后更新 size}public E get(){//当你从栈中取出元素时,根据栈的特性,应当从栈顶开始取出元素!!!E element =(E)stackArr[size-1];//具体理解见wordstackArr[size-1]=null;size--;return element;}public String toString() {StringBuilder sb = new StringBuilder();sb.append("stackArr:{ ");for (int i = 0; i < size; i++) {sb.append(stackArr[i]).append(" "); // 将每个元素的值拼接到 str 中}sb.append("}");return sb.toString();}public static void main(String[] args) {ArrayStack<Object> arrStack = new ArrayStack<>();for (int i = 0; i < 10; i++){arrStack.add(i);}System.out.println("存-"+arrStack.toString());for (int i = 0; i < 10; i++){System.out.print("取-"+arrStack.get()+" ");}}
}

输出结果:

存-stackArr:{ 0 1 2 3 4 5 6 7 8 9 }
取-9 取-8 取-7 取-6 取-5 取-4 取-3 取-2 取-1 取-0 

4.链表与栈

链表可以理解为实现一种长度不固定的栈。

1)栈中数据的插入与删除

由于栈只能从栈顶开始对其中的数据进行取出,所以我们只能倒着一一取出直至找到需要删除的数据,那么对于插入数据数据呢?一样也很麻烦,一旦越过最后一个数据要取出前面的就会很麻烦。

2)基本代码实现

链表通过将数据存入节点对象中,而节点类的构造一般包括属性、数据变量、下一个节点对象变量(其中存储的为地址)。

添加或查找数据都可以通过一个头节点依次向下找。

class Node<E>{E value;//数据变量Node<E> next;public Node(E value){this.value=value;}public Node<E> setNext(){return next;}public void getNext(){this.next=next;}}public class myLinkedList<E> {Node<E> head;int size;public void add(E e){Node<E> node = new Node<>(e);//如果头节点为空if(head==null){head=node;size++;return;}else{//遍历链表找到最后一个节点,将新节点挂在最后一个节点上//利用递归的思想Node<E> current = head;while (current.next != null){current=current.next;}current.next=node;size++;}}public static void main(String[] args) {myLinkedList<Integer> myll = new myLinkedList<>();long startTime = System.currentTimeMillis();for (int i = 0; i<100000;i++){myll.add(i);}long endTime = System.currentTimeMillis();System.out.println("人工链表用时:"+(endTime-startTime)+"ms");LinkedList<Integer> linkedList = new LinkedList<>();long startTime1 = System.currentTimeMillis();for (int i = 0; i<100000;i++){linkedList.add(i);}long endTime1 = System.currentTimeMillis();System.out.println("系统链表用时:"+(endTime1-startTime1)+"ms");}}

运行结果:

人工链表用时:5728ms

系统链表用时:4ms

思考:为何自制的链表与java系统自带的耗时差异如此之大?

可能的原因:在遍历上耗时过多。

3)头插法与尾插法

So如果我们不是通过找到头节点后再遍历循环挂到末尾上,直接让新节点成为头节点是不是就可以略去遍历循环的时间了呢?(头插法)

public void addFirst(E e){Node<E> node = new Node<>(e);if(head==null){head=node;size++;return;}else{node.next=head;//此时假设新节点node已经成为头节点,则当时的头节点的位置处于新节点的下一个head=node;//原本头节点的位置size++;}
}

运行结果

人工链表用时:98ms

系统链表用时:33ms

下面是尾插法的代码实现部分。

public void addLast(E e) {Node<E> node = new Node<>(e);if (head == null) {head = node;last = node;//此时头结点也是尾结点size++;return;} else {last.next = node;//此时假设新节点node已经成为头节点,则当时的头节点的位置处于新节点的下一个last = node;//原本头节点的位置size++;}
}

运行结果:

人工链表用时:94ms

系统链表用时:96ms

不难看出:尾插法的运行速度甚至比头插法还有java自带的耗时更少。

三、整体代码(叶赫那拉大战八国联军)

class Node<E>{E value;//数据变量Node<E> next;public Node(E value){this.value=value;}public void setNext(Node<E> next){this.next=next;}public Node<E> getNext(){return next;}}public class myLinkedList<E> {Node<E> head;Node<E> last;int size;public void addFirst(E e){Node<E> node = new Node<>(e);if(head==null){head=node;size++;return;}else{node.next=head;//此时假设新节点node已经成为头节点,则当时的头节点的位置处于新节点的下一个head=node;//原本头节点的位置size++;}}public void addLast(E e) {Node<E> node = new Node<>(e);if (head == null) {head = node;last = node;//此时头结点也是尾结点size++;return;} else {last.next = node;//此时假设新节点node已经成为头节点,则当时的头节点的位置处于新节点的下一个last = node;//原本头节点的位置size++;}}public void add(E e){Node<E> node = new Node<>(e);//如果头节点为空if(head==null){head=node;size++;return;}else{//遍历链表找到最后一个节点,将新节点挂在最后一个节点上//利用递归的思想Node<E> current = head;while (current.next != null){current=current.next;}current.next=node;size++;}}@Overridepublic String toString(){String str = "{";Node<E> current = head;while (current.next!=null){str+=current.value+",";current=current.next;}str+=current.value+"}";return str;}public E get(int point){if(point<0 || point>=size){System.out.println("不好意思这位大人您越界了");return null;}Node<E> current = head;for (int i =0; i<point;i++){current=current.next;}return current.value;}public static void main(String[] args) {myLinkedList<String> stringList = new myLinkedList<>();for (int i=0;i<6;i++){stringList.addLast("叶赫那拉"+i);}for (int i=0;i<2;i++){stringList.addFirst("八国联军"+i);}//注意顺序不能调换!!!System.out.println(stringList.toString());System.out.println(stringList.get(3));}public static void test(){myLinkedList<Integer> myll = new myLinkedList<>();long startTime = System.currentTimeMillis();for (int i = 0; i<1000000;i++){//myll.add(i);myll.addFirst(i);//myll.addLast(i);}long endTime = System.currentTimeMillis();System.out.println("人工链表用时:"+(endTime-startTime)+"ms");LinkedList<Integer> linkedList = new LinkedList<>();long startTime1 = System.currentTimeMillis();for (int i = 0; i<1000000;i++){linkedList.add(i);}long endTime1 = System.currentTimeMillis();System.out.println("系统链表用时:"+(endTime1-startTime1)+"ms");}}

运行结果:

{八国联军1,八国联军0,叶赫那拉0,叶赫那拉1,叶赫那拉2,叶赫那拉3,叶赫那拉4,叶赫那拉5}
叶赫那拉1

写到最后发现这篇的结构与内容有点杂乱,可能是因为有段时间没有写博客的原因,让我逐渐调整调整,争取下一篇是那种短小精悍的小短篇,后续关于链表、数组、栈的内容还会出现,这次就当做一个初步了解啦。

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

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

相关文章

四川景源畅信:如何更好的为抖音小店做引流?

在数字化营销的浪潮中&#xff0c;抖音小店作为新兴的电商形态&#xff0c;正以其独特的社交属性和流量优势吸引着众多商家的目光。如何为抖音小店引流&#xff0c;成为许多店主心中的疑问。本文将深入探讨有效提升店铺流量的策略&#xff0c;助你在抖音平台上快速崛起。 一、内…

代码随想录算法训练营第二十五天:树的最后学习

代码随想录算法训练营第二十五天&#xff1a;树的最后学习 如果不对递归有深刻的理解&#xff0c;本题有点难 单纯移除一个节点那还不够&#xff0c;要修剪&#xff01; #669. 修剪二叉搜索树 力扣题目链接(opens new window) 给定一个二叉搜索树&#xff0c;同时给定最小边界…

shell脚本之sort,uniq,tr,cut,sphit,paste,ecal与正则表达式

sort命令 uniq命令 tr命令 cut命令 sphit命令 paste命令 ecal命令 正则表达式 sort命令 sort命令---以行为单位对文件内容进行排序&#xff0c;也可以根据不同的数据类型来排序 比较原则是从首字符向后&#xff0c;依次按ASCII码值进行比较&#xff0c;最后将他们按升序…

通过java将数据导出为PDF,包扣合并单元格操作

最近项目中需要将查询出来的表格数据以PDF形式导出&#xff0c;并且表格的形式包含横向行与纵向列的单元格合并操作&#xff0c;导出的最终效果如图所示&#xff1a; 首先引入操作依赖 <!--导出pdf所需包--><dependency><groupId>com.itextpdf</groupId&…

汇聚荣:拼多多长期没有流量如何提高?

在电商的海洋中&#xff0c;拼多多以其独特的团购模式吸引了众多消费者的目光。然而&#xff0c;随着市场竞争的加剧和消费者需求的多样化&#xff0c;一些商家发现自家店铺的流量持续低迷&#xff0c;销售业绩难以突破。面对这样的挑战&#xff0c;如何有效提升拼多多店铺的客…

【计算机毕业设计】springboot反诈科普平台的设计与实现

相比于以前的传统手工管理方式&#xff0c;智能化的管理方式可以大幅降低反诈科普平台的运营人员成本&#xff0c;实现了反诈科普平台的 标准化、制度化、程序化的管理&#xff0c;有效地防止了反诈科普平台的随意管理&#xff0c;提高了信息的处理速度和精确度&#xff0c;能够…

[vue] nvm

nvm ls // 看安装的所有node.js的版本nvm list available // 查显示可以安装的所有node.js的版本可以在可选列表里。选择任意版本安装&#xff0c;比如安装16.15.0 执行&#xff1a; nvm install 16.15.0安装好了之后。可以执行&#xff1a; …

25考研英语长难句Day03

25考研英语长难句Day03 【a.词组】【b.断句】 多亏了电子学和微力学的不断小型化&#xff0c;现在已经有一些机器人系统可以进行精确到毫米以下的脑部和骨骼手术&#xff0c;比技术高超的医生用手能做到的精确得多。 【a.词组】 词组翻译thanks to多亏了&#xff0c;由于cont…

【JavaEE进阶】 Bean的作用域与生命周期

文章目录 &#x1f343;Bean的作用域&#x1f6a9;作用域的使用&#x1f6a9;观察Bean的作用域&#x1f388;单例作用域&#x1f388;多例作用域&#x1f388;请求作用域&#x1f388;会话作⽤域&#x1f388;Application作⽤域 &#x1f384;Bean的⽣命周期⭕总结 &#x1f34…

win11家庭中文版安装docker,报错 Docker Engine stopped

先引一下这位博主的链接超详细Windows11家庭中文版系统安装Docker-20230401_windows11安装docker-CSDN博客&#xff0c;我到前五步(跳出页面重启)和博主都是一样的&#xff0c;但是第六步我并没有报错&#xff0c;直接跳出docker界面 记录一下我的解决办法&#xff0c;首先按照…

金价又双叒涨了!现货黄金什么比较好

虽然近期有新闻显示&#xff0c;国内的实物黄金价格出现大幅的下跌&#xff0c;但是从整体看&#xff0c;多个黄金投资品种的长期上升趋势还是比较稳定的&#xff0c;因此我们会看到&#xff0c;很多投资者会趁现在这波下跌重新入场做多。那么投资黄金买什么比较好呢&#xff1…

如何向全国各大新闻网站投稿?

在信息爆炸的时代,新闻媒体的投稿工作对于单位的信息宣传员来说,既是一项重要的职责,也是一项充满挑战的任务。作为一名信息宣传员,我负责着单位的对外信息宣传投稿工作,每个月都需要在各大媒体上发表文章,以展示单位的成果和风采。 然而,刚开始的投稿之路并不顺畅。我习惯性地…

4种企业防泄密的办法,强烈推荐第二种

4种企业防泄密的办法&#xff0c;强烈推荐第二种 企业信息泄密常见的原因有内部人员、黑客、违规收集信息、第三方合作商&#xff0c;以下将为你详细分析这些泄密原因以及应对的方法。 1、内部人员泄密 内部员工由于能够接触到敏感数据&#xff0c;成为主要的泄露数据群体。这…

2024最新洗地机推荐,洗地机怎么选?热门品牌哪个最好用?

在现代生活中&#xff0c;忙碌的日常让家庭清洁变得更加繁重和耗时。然而&#xff0c;洗地机的引入彻底改变了这一状况。凭借其强大的清洁效果和简便的使用方式&#xff0c;洗地机能够迅速清除地面上的各种污垢&#xff0c;使清洁工作变得轻松自如。正因为如此&#xff0c;洗地…

JWT生成token工具类实现

JWT简介 JWT定义 JWT全称为Json web token&#xff0c;也就是 Json 格式的 web token JWT数据结构 1.JWT由三段字符串组成&#xff0c;中间用.分隔 Project_eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxIiwiZXhwIjoxNzE2MzcwMTM0LCJpYXQiOjE3MTU3NjUzMzQsImp0aSI6IjllO…

力扣HOT100 - 152. 乘积最大子数组

解题思路&#xff1a; 方法一&#xff1a;暴力 class Solution {public int maxProduct(int[] nums) {int max Integer.MIN_VALUE;int s 1;for (int i 0; i < nums.length; i) {s 1;for (int j i ; j < nums.length; j) {s * nums[j];max Math.max(max, s);}}ret…

出国旅游常用英语,柯桥成人英语培训

Where can I catch a taxi?哪里我可以叫到出租车&#xff1f; The taxi zone is right on the left corner over there.出租车站台就在左边转角处。 Are you free?您有空吗&#xff1f; Sure. Where are you going?当然。您要去哪里&#xff1f; Drive me back to Santa …

#Docker | Ngrok# 使用Ngrok和Docker进行内网穿透

一、注册 Ngrok官网注册&#xff0c;可以使用gmail或者outlook邮箱&#xff0c; 正常填写后你会收到一封电子邮件&#xff0c;点击邮件中链接即注册成功 二、获取密钥 登录&#xff0c;点击Your Authtoken&#xff0c;最上面copy左边就是你得密钥 三、使用内网穿透启动docker…

c++20---std::erase----std::erase_if

问题&#xff1a;如何删除满足条件的所有元素。 erase #include <iostream> #include <algorithm> #include <vector>int main(){std::vector<int> vec{1,2,3,1,1,1,1,1};std::erase(vec,1);for(int v:vec) std::cout<<v<<" "…

与禹老师学前端vue3学习汇总

24.5.15&#xff1a; 创建Vue3工程 1.确定自己电脑有没有nodejs环境&#xff0c;在cmd中输入node&#xff0c;如果出现Node.js的版本号说明已经有这个环境了&#xff0c;否则搜索Node.js安装 2.先在D盘创建一个文件夹Vue3_Study&#xff0c;然后在这个空文件夹中右键选择终端…