数据结构——栈

1、什么是栈?

栈其实就是一种数据结构,特点:先进后出。 

2、什么是java虚拟机栈?

此时 JVM stack 只是JVM当中的一块内存,该内存一般用来存放,例如:局部变量......

 

调用函数的时候,我们会为这个函数开辟一块内存,叫做栈帧。在哪里开辟呢?JVM stack

入栈和出栈顺序例题:

一个栈的入栈序列是 a,b,c,d,e,则栈的不可能的输出序列是( ) 。
a) edcba
b) decba
c) dceab
d) abcde

栈讲究先进后出,后进先出
选项1是abcde先入栈,然后依次出栈,正好是edcba

选项2是abcd先依次入栈,然后d出栈,e再入栈,e出栈

选项3是错误的,不可能a先出栈

选项4是a入栈,然后a出栈;b再入栈,b出栈。。。。。。依此类推

中缀表达式转后缀表达式(逆波兰表达式):

中缀表达式:(5+4)*3-2

过程:(((5+4)*3)-2)  --->  ((54)+*3)-2)  --->  (54+3)*-2)  --->  54+3*2-

后缀表达式:54+3*2-

如何通过后缀表达式计算一个值?(利用栈)

根据 逆波兰表示法,求表达式的值。

有效的算符包括 +-*/ 。每个运算对象可以是整数,也可以是另一个逆波兰表达式。

输入:tokens = ["2","1","+","3","*"]
输出:9
解释:该算式转化为常见的中缀算术表达式为:((2 + 1) * 3) = 9
class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for (int i = 0; i < tokens.length; i++){
            String s = tokens[i];
            if (!isOperation(s)){
                stack.push(Integer.parseInt(s));
            }else{
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch(s){
                    case "+":
                    stack.push(num1 + num2);
                    break;
                    case "-":
                    stack.push(num1 - num2);
                    break;
                    case "*":
                    stack.push(num1 * num2);
                    break;
                    case "/":
                    stack.push(num1 / num2);
                    break;
                }
            }
        }
        return stack.pop();

    }

    public boolean isOperation(String s){
        if (s.equals("+") || s.equals("-") || s.equals("*") || s.equals("/")){
            return true;
        }
        return false;
    }
}

栈的方法:

public class TestDemo {
    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);//[1, 2, 3, 4]
        System.out.println(stack.pop());//弹出栈顶元素,并且删除4
        System.out.println(stack.pop());//3
        System.out.println(stack.peek());//获取栈顶元素,但不删除2
        System.out.println(stack.empty());//false
        System.out.println(stack.isEmpty());//false

    }
}

3、自己实现一个栈

import java.util.Arrays;

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

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

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

    public boolean isFull(){
        return usedSize == elem.length;
    }
    
    public boolean isEmpty(){
        return usedSize == 0;
    }
    
    public int pop(){
        if (isEmpty()) {
            throw new RuntimeException();
        }
        int oldVal = elem[usedSize-1];
        usedSize--;
        return oldVal;
    }

    public int peek(){
        if (isEmpty()) {
            throw new RuntimeException();
        }
        int oldVal = elem[usedSize-1];
        return oldVal;
    }
}

此时我们自己实现的栈,底层是一个数组,那么请问:能不能用单链表实现一个栈? 

可以。满足两个要求:1、先进后出;2、入栈和出栈的时间复杂度得是O(1)

因为链表可以头插也可以尾插,那么入栈使用头插法还是尾插法?

假设:头插法入栈,时间复杂度是O(1),出栈的时候,只需要删除头节点[出栈]就好,时间复杂度也是O(1)。

如果入栈是尾插法,那么时间复杂度是O(n)了,因为尾插法每次都要找尾巴。

如果非要尾插法呢?但是还是做不到,此时你入栈是O(1)了,出栈呢?因为是单链表,虽然最后一个节点,我知道是谁,但是他的前一个我就不知道了。还要遍历去找这个节点的前驱,时间复杂度又是O(n).

其实最终的解决办法就是使用双向链表来实现一个栈,这样完全是可以的。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值