• 栈的使用
    • 栈的实现
    • 逆波兰式
    • 递归转化为循环
    • 括号匹配
    • 出入次序匹配
    • 最小栈

栈的使用

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

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
+45
6+7
+

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

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

递归转化为循环

递归的方式实现
栈_第3张图片
改成非递归;循环去写,栈,存进栈里再一个一个取出来
栈_第4张图片

括号匹配

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

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

出入次序匹配

判断出栈的顺序是否匹配题目
栈_第8张图片
逻辑:
栈_第9张图片

public class Solution {
    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操作,并能在常数时间内检索到最小元素的栈。
逻辑:需要两个栈;一个正常的放元素stack;一个放最小值smallstack(实时更新)
假设入栈序列:1309;最开始1放进去stack;发现smallstack没有元素就放进去。3放stack;发现比smallstack的栈顶元素大;那就不放。0放stack;发现比smallstack栈顶小;那就放入smallstack里。
如果有相同小的值;到底该放不放呢?必须放
因为你不放,如果你把这个值在栈1取出来,你栈2取不取呢,取2就没有这个最小值了,不取,你怎么知道栈1下面还有没有这个最小值

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();
            if(x == minStack.peek()) {
                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();
    }
}

你可能感兴趣的:(数据结构,java,开发语言)