Stack与栈(Java语言)

前言

通过前面的对于ArrayList的学习,我们知道了ArrayList底层就是一个数组,而数组存储数据,我们也可以换一种说法,叫做顺序表。而这篇博客我们就可以系统的介绍一下Stack,也就是栈这种数据结构。

前景介绍

在介绍Stack之前,我们先引入几个问题:

什么是栈?

简而言之,栈是一种数据结构,它的特点就是:先进后出。

举个例子:假如有一组数据12,23,34,45。
我们将数据放入栈中。
在这里插入图片描述
可以看到我们是按照12,23,34,45的顺序放入栈中的,那么拿出数据时,就需要先拿出45,34,23,最后拿出12这个数据,所以说叫做先进后出。

什么是Java虚拟机栈?

我们知道JVM内存结构分为五部分:Java虚拟机栈,本地方法栈,堆,方法区,程序计数器。所以我们可以说Java虚拟机栈是JVM当中的一块内存,该内存一般用来存放局部变量等,既然是栈,那么同样它具有栈的特点:先进后出。

什么是栈帧?

这边先挖一个坑,关于栈帧,我们会专门写一篇博客介绍栈帧,我们需要简单知道,当调用函数的时候,我们会专门为这个函数调用开辟一块内存,叫做栈帧。当一个函数结束,那么该函数的内存释放。

Java内置栈

对于Java而言,它是有内置的栈直接供我们使用的。也就是Stack类。

栈对象

跟ArrayList一样,通过new创建对象。

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
    }

栈方法

对于栈本身而言,栈自己有push()方法,pop()方法,peek()方法,empty()方法,search()方法。

push()方法

形式:public E push(E item)
解释:在栈的最顶部放入一个元素item。
例子:

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
    }

这时栈中依次放入1,2,3,4。

pop()方法

形式:public synchronized E pop()
解释:移除栈顶的元素,并返回该元素。
例子:

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
    }

结果:
在这里插入图片描述

peek()方法

形式:public synchronized E peek()
解释:返回栈顶元素,但并不删除。
例子:

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
    }

结果:
在这里插入图片描述

empty()方法

形式:public boolean empty()
解释:判断栈是否为null
例子:

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
        System.out.println(stack.empty());//栈中还有1,2,3
    }

结果:
在这里插入图片描述

search()方法

形式:public synchronized int search(Object o)
解释:如果栈中存在o这个元素,那么返回该元素离栈顶的距离,如果不存在则返回-1。
例子:

public static void main(String[] args) {
        Stack<Integer> stack = new Stack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        stack.push(4);
        System.out.println(stack.pop());//弹出栈顶元素,并且删除 4
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
        System.out.println(stack.peek());//获取栈顶元素,但不删除 3
        System.out.println(stack.empty());
        System.out.println(stack.search(3));
    }

结果:
在这里插入图片描述

实现栈

为了能够更好的学习栈,我们通过代码自己实现栈。

成员变量和构造方法

public class MyStack {
    public int[] elem;
    public int usedSize;

    public MyStack() {
        this.elem = new int[5];
    }
}

对于栈来说,底层可以用一个数组实现,因此我们需要一个数组存储元素,同样需要一个usedSize作为计数。构造方法只需要实例化一个5个元素的数组,如果不够扩容即可。

push()方法

public boolean isFull() {
        return this.usedSize == this.elem.length;
    }

public void push(int val) {
    if (isFull()) {
        //扩容
        this.elem = Arrays.copyOf(this.elem, 2 * this.elem.length);
    }
    this.elem[this.usedSize] = val;
    this.usedSize++;
}

在增加元素进入栈时,需要判断栈是否为满,如果为满,那么按照两倍进行扩容,如果没有满,那么在usedSize的位置放入val的值,并且usedSize++。

pop()方法

public boolean isEmpty() {
        return this.usedSize == 0;
    }

public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        int oldVal = this.elem[usedSize - 1];
        this.usedSize--;
        return oldVal;
    }

首先判断栈是否为null,如果栈为null,则无法弹出栈顶元素,因此抛出异常,否则,将数组中usedSize-1的位置的元素返回,并且usedSize–。

peek()方法

public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        return elem[usedSize - 1];
    }

与pop()方法类似,只是不需要usedSize-1即可。

search()方法

public int search(int val) {
        int count = usedSize - 1;
        while (elem[count] != val) {
            count--;
            if (count<0){
                return -1;
            }
        }
        return usedSize-count;
    }

将usedSize-1的值赋值给count,当count下标对应的元素不与val值相等,那么count–,直到相等或者count<0,如果相等,返回usedSize与count的差值,如果count<0返回-1。
关于栈我们就介绍到这里,栈的使用核心就是了解到它是先进后出的特点就行了,当然想要更快的掌握栈离不开刷题,如果有什么问题,或者建议,欢迎私信或者评论。谢谢各位!

  • 18
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 13
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 13
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Solitudefire

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值