动图演示:手撸堆栈的两种实现方法!

作者 | 王磊

来源 | Java中文社群(ID:javacn666)

转载请联系授权(微信ID:GG_Stone)

正式开始之前,先和各位朋友聊聊公众号后期的一些打算,后面的文章计划写一些关于数据结构和算法的内容,原因很简单「底层结构决定上层建筑嘛」,对于框架满天飞的今天,我们不止要学习如何使用框架,更要了解它的原理以及底层数据结构,只有这样我们才能更好的应用它。

当然,除了上述原因之外,还有一个重要因素是为了搞定面试。


随着软件开发行业竞争的日益激烈,面试的难度也在逐渐增加,因为企业要从众多的面试人中选出最优秀的人,只能提高面试的难度,而算法和数据结构比较烧脑的硬核技能之一,自然也就成了面试的首选科目。并且随着时间的推移,算法和数据结构出现的频率和占比也会不断增加,因此为了顺应时代发展的潮流,我们也要做一些调整,所以在后面的一些文章中,我会陆续更新一些关于算法和数据结构的文章,希望大家能够喜欢。

PS:当然随着智能系统的普及(如今日头条和抖音),算法和数据结构在企业中应用也越来越多,因此学习算法和数据结构也是迫在眉睫的事了。

栈定义

栈(Stack)又叫堆栈(简称栈),它是在同一端进行插入和删除数据的线性表。

栈是最基础也是最常见的数据结构之一,它的数据结构和操作流程如下图所示:


其中,允许进行插入和删除的一端叫作栈顶(Top),另一端叫作栈底(Bottom),栈底固定,栈顶浮动。

当栈中的元素为零时,该栈叫作空栈。添加数据时一般叫作入栈或进栈(Push),删除数据叫作出栈或退栈(Pop)。栈是后进先出(Last In First Out,LIFO)的线性表


物理结构 & 逻辑结构

在手撸算法之前,我们先来认识一下数据结构中的两个重要概念:物理结构和逻辑结构

当谈到“物理”和“逻辑”一词时,我们可以会想到数据库中的逻辑删除和物理删除。

所谓的物理删除是指通过删除命令真实的将数据从物理结构中删除的过程;而逻辑删除是指通过修改命令将数据更改为“已删除”的状态,并非真实的删除数据。

这里的逻辑结构和物理结构和上面的概念类似,所谓的物理结构是指可以将数据存储在物理空间中,比如数组和链表都属于物理数据结构;而逻辑结构则是用于描述数据间的逻辑关系的,比如本文要讲的栈就属于逻辑结构。


可能有些人看到这里就蒙了,没关系,我这里举一个例子你就明白了。

如果用人来表示物理结构和逻辑结构的话,那么真实存在的有血有肉的人就属于物理结构,而人的思想和信念就属于逻辑结构了


自定义栈I:数组实现

通过上面的内容,我们知道了栈属于逻辑结构,因此它的实现方式就可以有很多种了,比如数组的实现方式或者是链表的实现方式。那么我们就先用数组实现一下,栈的主要方法有:

① 定义结构

那么我们先来定义它的结构:

public class MyStack<E> {private Object[] value = null; // 栈存储容器private int top = -1; // 栈顶(的指针)private int maxSize = 0; // 栈容量// 构造函数(初始化默认容量)MyStack() {this.maxSize = 10;}// 有参构造函数MyStack(int initSize) throws Exception {if (initSize <= 0) {throw new Exception("栈容量必须大于 0");} else {value = new Object[initSize];maxSize = initSize;top = -1;}}
}

其中栈中数据会存储在 Object[] value 数组中,top 变量代表栈顶的指针,它其实存储的是栈顶元素的下标,会随着入栈不断变化(后进先出),maxSize 表示栈的最大容量。

② 入栈

此方法是给栈添加数据的,实现代码如下:

// 入栈(数据添加)
public boolean push(E e) throws Exception {if (maxSize - 1 == top) {throw new Exception("入栈失败,栈已满");} else {value[++top] = e;return true;}
}

每次当有数据插入时,只需在数组中添加一个值,并将栈顶的下标 +1 即可。

入栈操作如下图所示:

③ 出栈

此方法是删除栈中的数据的,实现代码如下:

// 数据移除(出栈)
public E pop() throws Exception {if (top <= -1) {throw new Exception("移除失败,栈中已无数据");} else {return (E) value[top--];}
}

出栈只需删除数组中栈顶数据(最后加入的数据),并修改栈顶下标 -1 即可。

出栈操作如下图所示:

④ 数据查询

除了以上操作方法之外,我们还需要添加一个查询栈顶数据的方法:

// 数据查询
public E peep() throws Exception {if (top <= -1) {throw new Exception("移除失败,栈中已无数据");} else {return (E) value[top];}
}

⑤ 代码测试

到此为止栈的数据结构就已经实现完了,接下来我们来测试一下:

// 代码测试
public static void main(String[] args) throws Exception {MyStack stack = new MyStack(10);stack.push("Hello");stack.push("Java");System.out.println(stack.peep());stack.pop();System.out.println(stack.pop());
}

以上程序的执行结果为:

Java

Hello

从上述代码可以看出,我们添加栈的顺序是 HelloJava 而输出的顺序是 JavaHello 符合栈的定义(后进先出)。

自定义栈II:链表实现

除了数组之外,我们可以还可使用链表来实现栈结构,它的实现稍微复杂一些,我们先来看链表本身的数据结构:

使用链表实现栈的流程如下:

也就是说,入栈时我们将数据存储在链表的头部,出栈时我们从头部进行移除,并将栈顶指针指向原头部元素的下一个元素,实现代码如下。

我们先来定义一个链表节点:

public class Node {Object value; // 每个节点的数据Node next; // 下一个节点public Node(Object value) {this(value, null);}/*** 创建新节点* @param value 当前节点数据* @param next  指向下一个节点(头插法)*/public Node(Object value, Node next) {this.value = value;this.next = next;}
}

接下来我们使用链表来实现一个完整的栈:

public class StackByLinked {private Node top = null; // 栈顶数据private int maxSize = 0; // 栈最大容量private int leng = 0; // 栈实际容量public StackByLinked(int initSize) throws Exception {if (initSize <= 0) {throw new Exception("栈容量不能小于等于0");}top = null;maxSize = initSize;leng = 0;}/*** 容量是否已满* @return*/public boolean isFull() {return leng >= maxSize;}/*** 是否为空* @return*/public boolean isEmpty() {return leng <= 0;}/*** 入栈* @param val* @return* @throws Exception*/public boolean push(Object val) throws Exception {if (this.isFull()) {// 容量已满throw new Exception("容量已满");}top = new Node(val, top); // 存入信息,并将当前节点设置为头节点leng++;return true;}/*** 出栈(移除)* @return* @throws Exception*/public Node pop() throws Exception {if (this.isEmpty()) {throw new Exception("栈为空,无法进行移除操作");}Node item = top; // 返回当前元素top = top.next;leng--;return item;}/*** 查询栈顶信息* @return*/public Node peek() throws Exception {if (isEmpty()) {throw new Exception("你操作的是一个空栈");}return top;}// 代码测试public static void main(String[] args) throws Exception {StackByLinked stack = new StackByLinked(10);stack.push("Hello");stack.push("Java");System.out.println(stack.peek().value);stack.pop();System.out.println(stack.pop().value);}
}

以上程序的执行结果是:

Java

Hello

总结

本文我们使用了数组和链表等物理结构来实现了栈,当然我们也可以使用其他容器来实现,比如 Java 中的 List,我们只需要保证在操作栈时是后进先出的执行顺序,并且至少包含 3 个重要方法:入栈、出栈和查询栈顶元素就可以了。

最后

算法和数据结构的学习是 3 分学 7 分练,只看不练是没办法学好算法的,而且学习算法和数据结构是一个循序渐进的过程,短时间内不会有明显的收效。因为这些算法经过了几百年的发展和积累才得以流传下来的,所以想要“玩得转”还需要一点耐心。

这里给你讲一个学习算法的“秘诀”:看不懂的知识要反复看,如果反复看还是看不懂,那么别着急,休息一下再继续看!相信我,对于学习算法这件事,所有人的过程都是一样的。


往期推荐

Java新特性:数据类型可以扔掉了?


图解|查找数组中最大值的5种方法!


URL 去重的 6 种方案!(附详细代码)


关注下方二维码,收获更多干货!

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

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

相关文章

Java中的异常处理

1 class YiChang{2 public static void main(String[] args){3 A anew A();4 a.show();5 }6 }7 8 class A{9 int[] i{1,2,3}; 10 public void show(){ 11 System.out.println(i[3]); 12 } 13 } 运行上面代码&#xff0c;会抛出这样…

数组copyWithin()方法以及JavaScript中的示例

JavaScript copyWithin()方法 (JavaScript copyWithin() method) copyWithin() method is used to copy the specified elements from an array and replace from specified index within the same array. It changes the this array (actual array). copyWithin()方法用于从数…

多图带你彻底理解Java中的21种锁!

作者 | 悟空聊架构来源 | 悟空聊架构&#xff08;ID&#xff1a;PassJava666&#xff09;本篇主要内容如下&#xff1a;本篇主要内容本篇文章已收纳到我的Java在线文档、 Github我的SpringCloud实战项目持续更新中帮你总结好的锁&#xff1a;序号锁名称应用1乐观锁CAS2悲观锁sy…

杨辉三角——数组解决

杨辉三角如图下所示&#xff0c;每一行的第一个数和最后一个数都为1&#xff0c;每一行中间的数&#xff08;出去第一个和最后一个&#xff09;a等于上一行与其相同列数的数b与数b前面的数之和。例&#xff1a; 第3行第2列的数是3&#xff0c;它就等于第2行第2列的数&#xff…

作文议论文开头结尾

一、 开头篇 1. Nowadays, it is commonly/widely/generally believed that…., but I wonder… 如今&#xff0c;人们普遍认为……&#xff0c;但是我怀疑…… 2. With the rapid growth of… … have/has become increasingly important in our daily life. 随着……的快速…

VS生成的exe文件如何在其他电脑上运行

在VS编译器上编写的程序都会生成一个exe文件&#xff0c;有时候写了一个很装逼的程序想在别人电脑炫耀一下&#xff0c;奈何将这个exe文件拷贝过去并不能运行&#xff0c;直接宣告装逼失败。为此将介绍一下如何将生成的exe文件在其他电脑上运行&#xff0c;步骤如下&#xff1a…

dumpstack_Java Thread类的静态void dumpStack()方法(带示例)

dumpstack线程类静态void dumpStack() (Thread Class static void dumpStack()) This method is available in package java.lang.Thread.dumpStack(). 软件包java.lang.Thread.dumpStack()中提供了此方法。 This method is used to print or display stack tracing of the cur…

netty websocket 简单消息推送demo

2019独角兽企业重金招聘Python工程师标准>>> 今天心情很不好&#xff01;&#xff01;&#xff01; 原因保密。 这篇是基于"netty与websocket通信demo"。 错误想法&#xff1a;大量客户请求&#xff0c;共用一个worker&#xff0c;来实现推送。 正确作法&…

给 JDK 官方提了一个 Bug,结果...

图 by&#xff1a;石头北京-望京关于作者&#xff1a;程序猿石头(ID: tangleithu)&#xff0c;现任阿里巴巴技术专家&#xff0c;清华学渣&#xff0c;前大疆后端 Leader。背景分享一下之前踩的一个坑&#xff0c;背景是这样的&#xff1a;我们的项目依赖于一个外部服务&#x…

Of Study - Francis Bacon

Of StudyFrancis Bacon 弗朗西斯培根Studies serve for delight, for ornament, and for ability. Their chief use for delight, is in privateness and retiring; for ornament, is in discourse;and for ability, is in the judgment and disposition of business.For expe…

解决exe文件在别人电脑上运行缺失文件情况

这里就以vs2013为例&#xff1a;编译后生成的exe文件拷贝到别人电脑上运行是会弹出一个窗口说缺失MSVCR120.dll和MSVCR120D.dll这两个文件。&#xff08;其他vs版本的编译器在所提示的缺失文件按下述方法也可解决&#xff09;下面就介绍一种方法解决。 1、在VS2013软件中找到MS…

Java日历的getMinimalDaysInFirstWeek()方法和示例

Calendar类的getMinimalDaysInFirstWeek()方法 (Calendar Class getMinimalDaysInFirstWeek() method) getMinimalDaysInFirstWeek() method is available in java.util package. getMinimalDaysInFirstWeek()方法在java.util包中可用。 getMinimalDaysInFirstWeek() method is…

HighCharts: 设置时间图x轴的宽度

这个x轴宽度的设置整了好久&#xff0c;被老板催的要死highcharts的api文档很难找&#xff0c;找了半天也没找到&#xff0c;网上资料少&#xff0c;说的试了下&#xff0c;也没有&#xff0c;我用的图里api文档里没有介绍&#xff0c;这个属性不知道的话&#xff0c;根本不好找…

32张图带你彻底搞懂事务和锁!

作者 | 悟空聊架构来源 | 悟空聊架构&#xff08;ID&#xff1a;PassJava666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;PassJava&#xff09;本篇主要内容如下&#xff1a;本篇主要内容一、事务1.1 什么是事务为单个工作单元而执行的一系列操作。如查询、修改数…

C++总结篇(1)命名空间及引用

1、命名空间 1.1概念&#xff1a; 用我自己的话说就是规定一个空间&#xff0c;在该空间内定义的变量和函数只限于在该空间内使用&#xff0c;在该空间外无法直接调用。需要调用须加域名&#xff0c;这也就使得避免了同名变量或者函数引起的冲突。 1.2命名空间定义: 定义命名空…

分布式映射与集中式映射_K映射上的表达式映射和组包围

分布式映射与集中式映射In the previous article (Karnaugh Map 2, 3 and 4- variable) we have already discussed the designing of K-Map and various forms in which they are represented based on either they are being mapped for minterm or maxterm. 在上一篇文章( 卡…

phrases

短语 To get the better/best of you 打败&#xff0c;胜过To get the most/utmost out of 有效地使用或利用Overall trend Compactly- built a man of medium build Heavily-built Level off, remain stable, stay constantPlateau fluctuateThe outlay on cars are …

Datagridview拖放数据到TreeView

通过Datagridview控件可以显示数据库记录sender:表示支持.net framework类层次结构中所有类的基类对象.e:表示为mousedown 事件提供数据.private void treeview1_mouseenter(object sender,eventargs e)拖放可以选定单行或者多行.1.选定一条在控件中默认状态下行标题选定.按ctr…

JDK 竟然是这样实现栈的?

作者 | 王磊来源 | Java中文社群&#xff08;ID&#xff1a;javacn666&#xff09;转载请联系授权&#xff08;微信ID&#xff1a;GG_Stone&#xff09;前面的文章《动图演示&#xff1a;手撸堆栈的两种实现方法&#xff01;》我们用数组和链表来实现了自定义的栈结构&#xff…

layui如何自定义layedit富文本编辑器工具栏

layui自带了layedit富文本编辑器&#xff0c;我们在使用过程中有时候不需要全部工具&#xff0c;或者想自定义工具栏&#xff0c;该如何弄呢&#xff1f;以下方法教大家自定义自己的layedit编辑器。 步骤1&#xff1a;定义存放编辑器的盒子 <div class"layui-form-it…