栈的使用

栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则
栈是先进先出的数据结构;怎么构思呢;很容易和队列记反。你自己想;队列;排队的队;排队坐高铁;先进去的人先走出到高铁站。栈是反着的。
在这里插入图片描述

import java.util.Stack;

public class stack {
    
    public static void main(String[] args) {

        Stack<Integer> stack=new Stack<>();
       if(stack.empty()==true){//是否为空
           System.out.println("是的为空");
       }
        stack.push(1);
        stack.push(12);
        stack.push(123);
        stack.push(1234);
        stack.push(12345);
        int x=stack.pop();//取栈顶元素
        System.out.println(x);
        System.out.println(stack.peek());//瞄一眼栈顶元素
    }

}

栈的实现

这个集合类底层是数组还是链表呢? 数组


import java.util.Arrays;
import java.util.Stack;


    public class Mystack {

        public int[] elem;
        public int usedSize;
        public static final int DEFAULT_SIZE = 10;

        public Mystack() {
            this.elem = new int[DEFAULT_SIZE];
        }

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

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

        public int pop(){
            if (usedSize==0){
                System.out.println("栈为空;不能出栈;严谨一点应该报异常;避免元素值真的是负一");
                return -1;
            }
            //返回了;还得给栈的长度减1
            int ret=elem[usedSize--];
            usedSize--;
            return ret;//直接return [--usedSize];更高效

        }

        public boolean empty(){//有效元素是否为0
            return usedSize==0;
            
        }

        public int peek(){
            if (empty()){
                System.out.println("栈为空");
                return -1;
            }
            return elem[usedSize-1];
        }
        
        public static void main(String[] args) {
            Mystack mystack=new Mystack();
            mystack.push(100);
        }

}

逆波兰式

假设:这有一个中缀表达式:a+bc+(de+f)g;如何转成后缀表达式
1:按从左到右加减乘除的优先级加括号:
2:先处理乘号变成:a+(b
c)+( ((d *e)+f)g)
3:再处理加号变成:((a+(b
c) )+( (((d *e)+f) )*g))
4:把这些符号挪到对应的括号后面(如果放前面就叫前缀表达式):挪完把括号去掉
在这里插入图片描述

后缀表达式求值

给你应该后缀表达式求结果;怎么求呢? 1 2 3*+456+7+

代码逻辑:
创建一个栈遍历这个字符串;如果是数字则放进栈里;遇到运算符则取出栈顶的两个元素;搭配这个符号;最顶的作为右操作数;其次的作为左操作数。先得到2 *3;计算的结果为6再放进栈里
在这里插入图片描述

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
    //  只需要把数字传进去,当我们遇到数字的时候,利用字符串转数字的方法就好了
            for(int i=0;i<tokens.length;i++){
                String t=tokens[i];
               //这里不能省略 String t=tokens[i];switch (tokens[i])。switch有传入类型要求,tokens[i]是string []类型
            switch (t){
                case "+": 
                    stack.push(stack.pop() + stack.pop());//直接就取出来操作了,放进去,。
                                                     
                    break;
                case "-":
                    int num = stack.pop();
                    stack.push(stack.pop() - num);
                    break;
                case "*":
                    stack.push(stack.pop() * stack.pop());
                    break;
                case "/":
                    int num2 = stack.pop();
                    stack.push(stack.pop() / num2);
                    break;
                default:
                    stack.push(Integer.valueOf(t));//数字字符串入栈,得转类型,如果是数字自动走到这行
            }
        }
        return stack.pop();
    }
}

递归打印链表转化为循环

递归的方式实现:你还可以反转链表呢

   public  void displayLink(ListNode head){
            //就是递到尾再归。
        ListNode cur=head;
        if(cur!=null){
            displayLink(cur.next);
            System.out.print(cur.val);
        }
    }

改成非递归;循环去写,栈,存进栈里再一个一个取出来

   public void display(ListNode head){
        ListNode cur=head;
        Stack<ListNode> stack=new Stack<>();
        while (cur!=null){
            stack.push(cur);
            cur=cur.next;
        }
        while (!stack.empty()){
            System.out.print(stack.pop().val);

        }

    }

括号匹配

字符串写法:这种方式确实很不错;如果括号是在一起的就能直接替换掉;如果是这种包含[ ( ) ];第一次[ ]就没法替换掉;所以需要循环;考虑最坏情况。所有的括号只有一对在一起。

    public boolean isValid(String s) {
        int length = s.length() / 2;
		for (int i = 0; i < length; i++) {
			s = s.replace("()", "").replace("{}", "").replace("[]", "");
		}
		return s.length() == 0;
    }

括号匹配
在这里插入图片描述
不能通过括号个数来判断的;顺序上有要求我们就用栈;正常情况一定是左右都有的
在这里插入图片描述
逻辑:因为异常情况是非常多;但是我们可以选择正确的情况;剩下就是异常的。只要是左括号往栈里放;如果遇到右括号那就取栈顶的匹配一下看看是否合适。(还有种特殊情况我们上面是没涉及到;栈为空有右括号);最后如果遍历完;栈里还不为空就说明左括号有多。

注意:它输入的字符串全是括号的那种;所以不是左括号就是右括号。这里ch不是左括号就是右括号;如果是左括号则执行if添加进栈里;如果是右括号则走else;去取栈顶瞄一眼(直接取都行啊;反正匹配的话你也要取元素;不匹配就直接返回false);对比一下是否匹配

 public static boolean isValid(String s){
         //两个方式;要么判断错误情况;要么判断正确情况。这题当然判断正确情况
        // 就消消乐嘛;里面的先消;然后外面的就能消了 。[({ })]、[{} ()]

        //思路很简单;左括号放栈里;遇到右括号取栈顶看看匹不匹配。
        Stack<Character> stack=new Stack<>();
        for (int i = 0; i <s.length() ; i++) {
            if(s.charAt(i)=='('||s.charAt(i)=='['&&s.charAt(i)=='{'){
                stack.push(s.charAt(i));
            }else {
                if(stack.empty()){
                    return false;
                }
                char ch=stack.pop();
                if((ch=='('&&s.charAt(i)==')') ||(ch=='{'&&s.charAt(i)=='}') ||(ch=='['&&s.charAt(i)==']')){
                    continue;

                }else {
                    return false;
                }


            }

        }
        if(!stack.empty()){//左括号有多的情况
            return false;
        }

        return true;
    }

出入次序匹配

判断出栈的顺序是否匹配题目
在这里插入图片描述
逻辑:
在这里插入图片描述

public class Solution1 {
    public boolean IsPopOrder(int [] pushA, int [] popA) {

        Stack<Integer> stack = new Stack<>();
        int j = 0;
        for (int i = 0; i < pushA.length ; i++) {
            stack.push(pushA[i]);

            while (!stack.empty()&&stack.peek() == popA[j]) {//瞄一眼相不相等,相等我再取出来
                    stack.pop();
                    j++;
                }

            }
                return stack.empty();

        }
    }
  

最小栈

题目链接
设计一个支持 push ,pop,peek操作,并能在常数时间内检索到最小元素的栈。
其实很简单:就是普通的创建一个栈;但是你需要另一个栈存最小值

push:入栈你得考虑是不是最小的这个值;是最小就得一起放入最小栈。注意:相等的最小得一起放入(不然你不知道出这个值时;最小栈出还是不出)。
top没什么好说的;就是peek瞄一眼栈顶。
pop:你如果出的是最小值你得连最小栈的一起出。但是当使用最小值都出完;最小栈为null;你得考虑更新这个最小栈。
getMin:去最小栈栈顶瞄一眼即可

import java.util.Stack;

class MinStack {

    private Stack<Integer> stack1;
    private Stack<Integer> minStack;

    public MinStack() {
        stack1 = new Stack<>();
        minStack = new Stack<>();
    }
    
    public void push(int val) {
        stack1.push(val);
        if(minStack.empty()) {
            minStack.push(val);
        }else {
            int x = minStack.peek();
            if(val <= x) {
                minStack.push(val);
            }
        }
    }
    
    public void pop() {
        if(!stack1.empty()) {
            int x = stack1.pop();//在栈1弹出;如果是最小值;在最小栈也弹出
            if(x == minStack.peek()) {
            //虽然力扣能通过;这里有个bug但是你这样子下一次不就不能取最小值吗;minstack都没元素了。
              //你得更新最小值啊;这时候最小栈是null吗;也不一定;可能还有其它相同的值最小值。你就判断如果是null就更新最小值;先把pop倒入最小栈里;然后再倒回去;这个过程记录最小值(用数组存;因为可能多个最小值是一样;得全部存进去)。最把这个放入最小值 
                minStack.pop();
            }
            
        }
    }
    //只针对 普通的栈来说的 获取普通栈的栈顶元素 相当于peek函数
    public int top() {
        if(!stack1.empty()) {
            return stack1.peek();
        }
        return -1;//不要抛异常
    }
    
    public int getMin() {
        if(minStack.empty()) {
            return -1;
        }
        return minStack.peek();
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

20计科-廖雨旺

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

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

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

打赏作者

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

抵扣说明:

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

余额充值