Java集合框架:栈、Stack详解

目录

一、栈

二、栈的使用

         1. Stack类

2. 栈的模拟实现

三、栈的应用场景

1. 改变元素的序列

2. 将递归转化为循环(如:逆序打印链表)

3. 栈的oj题练习(oj题中都用到了栈这种数据结构)

四、栈,虚拟机栈,栈帧的区别


前言

    栈是一种数据结构,一种特殊的线性表,只允许在固定的一端进行插入和删除元素操作。数据插入和删除的操作的一端称作栈顶,另一端称作栈底。栈中的数据元素遵守一个原则:先进后出。   

一、栈

压栈:栈的插入操作叫做压栈/ 进栈,压栈在栈顶操作。

出栈:栈的删除操作叫做出栈,出栈数据也是在栈顶。

 如下图解:

     栈中的数据元素遵循后进先出的原则(Last in first out)就像子弹的上膛操作和射击操作。

二、栈的使用

    在Java集合框架中,栈使用的具体类是Stack,(但是并不是只有Sack一个类可以当作栈来使用)接下来就具体介绍下集合框架中栈的使用。

 1. Stack类

    Stack类的方法的使用:

Stack()实例化一个栈(此时栈是空的)

E push(E e)

压栈操作,将e元素入栈,并返回e
E pop()将栈顶元素出栈并返回
E peek()获取栈顶元素(但此时栈顶元素并没有出栈,只是看了一眼栈顶元素是哪个)
int size()获取栈中有效元素个数
boolean empty()判断栈是否为空(是否有元素),返回值为布尔类型

    栈方法的使用演示:

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.size());
        System.out.println(stack.peek());
        System.out.println(stack.pop());
        System.out.println(stack.size());
        System.out.println(stack.empty());
    }

要想真正了解Stack类中方法实现的逻辑最好还是模拟实现一个栈;

2. 栈的模拟实现

//用数组/顺序表实现的栈
//顺序栈

public class MyStack {
    public int[] elem;
    public int usedSize;
    public MyStack() {
        this.elem = new int[10];
    }
    //压栈
    public void push(int val) {
        if (isFull()) {
            elem = Arrays.copyOf(elem,2*elem.length);
        }
        elem[usedSize++] = val;
    }
    public boolean isFull() {
        return usedSize == elem.length;
    }
    //出栈
    public int pop() {
        if (isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        /*int val = elem[usedSize - 1];
        usedSize--;
        return val;*/
        return elem[--usedSize];
    }
    public boolean isEmpty() {
        return usedSize == 0;
    }
    //求栈中元素个数
    public int size() {
        return usedSize;
    }
    //获取栈顶元素
    public int peek() {
        if (isEmpty()) {
            throw new EmptyException("栈是空的!");
        }
        return elem[usedSize - 1];
    }

三、栈的应用场景

1. 改变元素的序列

 2. 将递归转化为循环(如:逆序打印链表)

     几种打印链表的方式:

//递归打印链表(逆序打印链表)
    public void display3(ListNode pHead) {
        if (pHead == null) return;
        if (pHead.next == null) {
            System.out.print(pHead.val + " ");
            return;
        }
        display3(pHead.next);
        System.out.print(pHead.val + " ");
    }

    //用栈结构打印链表(逆序打印链表)
    public void display4() {
        Stack<ListNode> stack = new Stack<>();
        ListNode cur = head;
        while (cur != null) {
            stack.push(cur);
            cur = cur.next;
        }
        //遍历栈
        while (!stack.isEmpty()) {
            ListNode top = stack.pop();
            System.out.print(top.val + " ");
        }
        System.out.println();
    }
    //遍历打印链表
    public void display() {
        ListNode cur = head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

3. 栈的oj题练习(oj题中都用到了栈这种数据结构)

1. 括号匹配    力扣思路:用栈这种数据结构即可解决问题:遇到的左括号就入栈,如果遇到右括号就获取栈顶元素进行匹配,能够匹配就出栈。 最后看栈是否为空,如果站空,则括号就是匹配的。
2. 逆波兰表达式求值    力扣思路:遇到操作数就入栈,遇到运算符就出栈两个操作数(注:先出右操作数,再出左边操作数) ,进行运算,之后把运算结果入栈,然后重复上述操作,最后栈中的元素就是表达式的结果。
3. 出栈入栈次序匹配    栈的压入、弹出序列_牛客题霸思路:先入栈压入序列,在压入序列入栈的过程中,判断出栈序列中的数据和入栈序列中的数据是否相同,如果相同就开始出栈,最后看栈是否为空,如果栈空,入栈序列和出栈序列就是相对应的。
4. 最小栈    力扣思路:用两个栈,其中一个放入的元素是入栈的序列,另一个栈维护最小值,当minStack空时,先入栈第一个元素,之后和入栈序列中的元素进行比较,如果minStack中的栈顶元素比当前入栈元素大,此时就更新minStack中的最小值。

四、栈,虚拟机栈,栈帧的区别

是一种数据结构,在Java标准库中有对应的实现 --> Stack类,而Stack类是继承于Vector的,和Vector的区别:Stack不是线程安全的,而Vector是线程安全的。

虚拟机栈是一块有特殊作用的内存空间,jvm为了对数据更好的管理,将内存按照不同的需求划分出的一种结构。 栈区:包含方法调用的相关信息,最主要的就是栈帧,其中栈帧是按照栈这种数据结构实现的。
栈帧当new一个对象或赋值内置类型时,jvm就会在栈区中开辟一块空间,这块空间就是在栈区中,栈帧也是一种结构,包含局部变量表,操作数....每个方法在运行时,jvm都会创建一个栈帧,然后将栈帧入栈到虚拟机栈中执行方法体,当方法调用结束时,该方法对应的栈帧就会从虚拟机中出栈。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

良月初十♧

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

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

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

打赏作者

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

抵扣说明:

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

余额充值