栈的学习,及部分题目

目录

1.栈

1.1栈的概念

1.2栈的使用

java自带栈的使用

数组实现栈

链表实现栈

1.3相关题目

逆波兰表达式求值

代码实现

有效的括号

代码实现

栈的压出、弹出序列

代码实现

最小栈

代码实现


1.栈

1.1栈的概念

特点:先进后出,后进先出的形式组织数据

1.2栈的使用

java自带栈的使用

 public static void main(String[] args) {
        //实例化一个stack对象
        Stack<Integer> stack=new Stack<>();
        stack.push(1);//先进来的放栈底
        stack.push(2);//依次往上放
        stack.push(3);
        stack.push(4);//最后一个在栈顶

        //pop的返回类型是一个E,这里是Integer,将栈顶元素推出栈
        System.out.println(stack.pop());
        //peek只是看一眼栈顶函数,而不会将他推出
        Integer ret=stack.peek();

        System.out.println(ret);
        ret=stack.peek();
        System.out.println(ret);
        //size获取栈中元素个数
        System.out.println(stack.size());
    }

栈的底层是一个数组

数组实现栈
//需要实现的接口
public interface IStack {
    void push(int x);
    int pop();

    int peek();

    int size();

    boolean empty();

    boolean full();

}

public class EmptyException extends RuntimeException {
    public EmptyException(String msg){
        super(msg);
    }

}

package stackdemo;

import java.util.Arrays;

public class MyStack implements IStack {

    private int[] elem;
    private int usedSize;

    //创建一个默认大小
    private static final int DEFAULY_CAPACITY=10;

    //创建一个默认大小的数组
    public MyStack(){
        elem=new int[DEFAULY_CAPACITY];

    }

    @Override
    public void push(int x) {
        //满了就进行2倍扩容
        if (full()){
            //copyof是返回一个数组
            elem= Arrays.copyOf(elem,2*elem.length);
        }
        //usedSize是一个指针指向数组中最后一个元素之后
        //及usedSize还可以存放数据下标
        elem[usedSize]=x;
        usedSize++;

    }

    @Override
    public int pop() {
        //先判断是否为空再推出
        if (empty()){
            throw new EmptyException("栈空了");
        }
        int old=elem[usedSize-1];//先存下最后一个元素
        //相当于是删除,最后一个元素依然在数组里面,只不过指针位置指向了他
        //当增加时会把他覆盖,所以数组的删除是覆盖
        usedSize--;
        //当是引用类型elem[us]=null;
        return old;
    }

    @Override
    public int peek() {
        //先判断是否为空再推出
        if (empty()){
            throw new EmptyException("栈空了");
        }
        int old=elem[usedSize-1];//先存下最后一个元素
        //相当于是删除,最后一个元素依然在数组里面,只不过指针位置指向了他
        //当增加时会把他覆盖,所以数组的删除是覆盖
        //usedSize--;不删就是没得这一步
        //当是引用类型elem[us]=null;
        return old;
    }

    @Override
    public int size() {
        return usedSize;
    }

    @Override
    public boolean empty() {
        return usedSize==0;
    }

    @Override
    public boolean full() {//判断数组是否满
        if (usedSize==elem.length){
            return true;
        }
        return false;
    }
}
链表实现栈

单链表

从尾出或入时,每次都要遍历到最后一个节点,时间复杂度较高

用双链表LinkedList

1.3相关题目

逆波兰表达式求值
代码实现

计算的时候遇到运算符之后运算符前一个在运算符右边,运算符前前一个在运算符左边,然后计算后再存入栈中,代替运算符及其前两个。

    public int evalRPN(String[] tokens) {
        Stack<Integer> stack=new Stack<>();

        for (String x:tokens){
            if (!isOperation(x)){
                stack.push(Integer.parseInt(x));

            }else {
                int num2=stack.pop();
                int num1=stack.pop();
                switch (x){

                    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();

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

    }
有效的括号
代码实现

其实就三种情况

1.左括号多

2.右括号多

3.一样多但左右不匹配

思路:左括号入栈,遇到右括号时,比较栈顶元素是否匹配,匹配就pop一下出栈

什么时候匹配?当栈当中元素为空并且字符串也遍历完成

    public boolean isValid(String s) {
        Stack<Character> stack=new Stack<>();

        //1.遍历字符串
        for (int i = 0; i < s.length(); i++) {
            char ch=s.charAt(i);

            //2.判断是不是左括号
            if (ch=='{'||ch=='['||ch=='('){
                stack.push(ch);

            }else {//此时的ch已经是右括号了
                //3.遇到右括号
                if (stack.empty()){//如果栈是空的不匹配,这个函数是空的会返回true
                    return false;
                }
                char ch2=stack.peek();//判断是哪个左括号
                if ((ch2=='{'&&ch=='}')||(ch2=='['&&ch==']')||(ch2=='('&&ch==')')){
                    //出去这个匹配的左括号
                    stack.pop();
                }else {
                    return false;
                }
            }
        }
        //里面还有左括号的情况
        if (!stack.empty()){
            return false;
        }
        return true;


    }
栈的压出、弹出序列
代码实现

popV是否可能是pushV的出栈序列

思路:

1.遍历push数组,把元素放到栈中

2.每push一个元素,就和pop中数组的元素比较

3.如果相等j++且出栈

4.如果不相等想办法入栈

 public boolean IsPopOrder (int[] pushV, int[] popV) {

        Stack<Integer> stack=new Stack<>();
        int j=0;
        for (int i = 0; i < pushV.length; i++) {
            //数组放进栈里
            stack.push(pushV[i]);//先把相等的放了一个进去,下一步出
            while (!stack.empty()&&j<popV.length&&stack.peek()==popV[j]){
                stack.pop();//移除相等的数组

                j++;
            }

        }
        return stack.empty();//移除完了就等于匹配完了,栈就空了
    }
最小栈
代码实现

思路

使用两个栈,一个栈存放元素,一个栈存最小元素,第一个元素都要存,当后面元素比第一个元素小时,存入minStack中,当要返回最小时直接pop()minStack

删除时,当右边元素等于左边栈顶元素时,右边元素也要删除

class MinStack {

    private Stack<Integer> stack;
    private Stack<Integer> minstack;


    private int usedSize;

    public MinStack() {
        stack = new Stack<>();
        minstack = new Stack<>();


    }

    public void push(int val) {
        stack.push(val);

        if (minstack.empty()) {
            minstack.push(val);
        } else {
            int peekVal = minstack.peek();
            if (val <= peekVal) {//等于的情况也需要
                minstack.push(val);
            }
        }
    }

    public void pop() {
        if (!stack.empty()){
            int val=stack.pop();
            if (!minstack.empty()){
                if (val==minstack.peek()){
                    minstack.pop();
                }
            }
        }
    }

    //获取当前普通栈的栈顶元素
    public int top() {
        return stack.peek();


    }

    public int getMin() {
        if (!minstack.empty()){
           return minstack.peek();
        }
        return -1;

    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值