java 自己实现栈_JDK 竟然是这样实现栈的?

在正式开始之前,先给大家再解释一下「堆栈」一词的含义,因为之前有读者对这个词有一定的疑惑。

Stack翻译为中文是堆栈的意思,但为了能和Heap(堆)区分开,因此我们一般将Stack简称为栈。因此当“堆栈”连在一起时有可能表示的是Stack,而当“堆、栈”中间有分号时,则表示Heap(堆)和Stack(栈),如下图所示:

23a7eab128c40b662c7c79cc2149bd85.png

JDK 栈的实现

聊会正题,接下来我们来看 JDK 中是如何实现栈的?

在 JDK 中,栈的实现类是Stack,它的继承关系如下图所示:

12400c2eff3391cb89c006fb59aa5fe5.png

Stack 包含的方法如下图所示:

772c312376b1f8d1abeeab45e85fabd1.png

其中最重要的方法有:

push:入栈方法(添加数据);pop:出栈并返回当前元素(移除数据);peek:查询栈顶元素。Stack 实现源码如下:

d690ab4043e673ae841593ffb414d6b6.png

b8c5dca184b62571091d6118f3c9378e.png

从上述源码可以看出,Stack 中的核心方法中都调用了父类Vector 类中的方法,Vector 类的核心源码:

e83eaa3de8fc7cefdd8effa5afbd9314.png

410906144f0faa3e6223bb52fdbc613f.png

对于上述源码中,可以最不好理解的就是System#arraycopy 这个方法,它的作用其实就是将删除的元素(非末尾元素)的后续元素依次往前移动的,比如以下代码:

4e8fd91fb6355b9378f28328548e3375.png

它的运行结果是:

[Java, Hello, world, JRE, JRE]

也就是说当我们要删除下标为 3 的元素时,需要把 3 以后的元素往前移动,所以数组的值就从{"Java", "Hello", "world", "JDK", "JRE"} 变为了[Java, Hello, world, JRE, JRE],最后我们只需要把尾部元素删除掉,就可以实现数组中删除非末尾元素的功能了。

小结

通过以上源码可以得知,JDK 中的栈(Stack)也是通过物理结构数组实现的,我们通过操作物理数组来实现逻辑结构栈的功能,关于物理结构和逻辑结构详见《动图演示:手撸堆栈的两种实现方法!》。

栈的应用

经过前面的学习我们对栈已经有了一定的了解了,那栈在我们的平常工作中有哪些应用呢?接下里我们一起来看。

浏览器回退

栈的特性为 LIFO(Last In First Out,LIFO)后进先出,因此借助此特性就可以实现浏览器的回退功能,如下图所示:

1c6b1614d7b60c4302a6f40068428bf6.png

函数调用栈

栈在程序中最经典的一个应用就是函数调用栈了(或叫方法调用栈),比如操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。为了让你更好地理解,我们一块来看下这段代码的执行过程。

b19230202c3489fd76b83d365b06889d.png

从代码中我们可以看出,main()函数调用了add()函数,获取计算结果,并且与临时变量a相加,最后打印res的值。为了让你清晰地看到这个过程对应的函数栈里出栈、入栈的操作,我画了一张图。图中显示的是,在执行到add()函数时,函数调用栈的情况。

0cd54a386c7d335765dd54637c476e3f.png

栈的复杂度

复杂度分为两个维度:

时间维度:是指执行当前算法所消耗的时间,我们通常用「时间复杂度」来描述;空间维度:是指执行当前算法需要占用多少内存空间,我们通常用「空间复杂度」来描述。这两种复杂度都是用大 O 表示法来表示的,比如以下代码:

e355573f45cd8b40bb54e2da7f1e8a97.png

用大 O 表示法来表示的话,它的时间复杂度就是 O(n),而如下代码的时间复杂度却为 O(1):

043429feed21f2f80d3e53ec9e7696d3.png

因此如果使用大 O 表示法来表示栈的复杂度的话,结果如下所示:

555dd25701b793f73af95d2463507a96.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值