【JAVA】数据结构——栈的实现 和 常见面试题

目录

1.栈的基本.概念

2.栈的实现

1.顺序表实现:利用尾插和尾删的方式实现

2.链表实现:头尾皆可实现

面试题1:有效字符串的实现

面试题2:输入两个序列,第一个int[] pushA表示栈的压入顺序,判断第二个序列int[] poppA是否为弹出序列。

面试题3:根据 逆波兰表示法(后缀表达式),求表达式的值

面试题4:设计一个支持 push ,pop ,top 操作,并在常数时间内检索到最小元素的栈。


1.栈的基本.概念

1.栈:特殊的线性表

在固定的一端(栈顶)进行数据插入与删除,遵循后进先出(Last In First Out,LIFO)原则。

压栈:数据的写入(也叫进栈、入栈);        出栈:数据的删除

2.基本方法:栈的几种主要基本操作:
void push(int data):入栈
int pop():出栈(删除并返回最后一个插入栈的元素)
int peek():查看栈顶元素
boolean empty():判断是否为空


2.栈的实现

1.顺序表实现:利用尾插和尾删的方式实现

注意:入栈之前要先判断顺序表容量是否够,不够则需进行扩容 Arrays.copyOf()

this.elem = Arrays.copyOf(this.elem,2*this.elem.length);

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

    public MyStack() {
        this.elem = new int[5];
    }
    @Override
    public String toString() {
        return "MyStack{" +
                "elem=" + Arrays.toString(elem) +
                ", usedSize=" + usedSize +
                '}';
    }
//入栈
    public void push(int val) {
        if (isFull()) {
            //扩容
            this.elem = Arrays.copyOf(this.elem,2*this.elem.length);  //2倍数扩容
        }
        this.elem[this.usedSize] = val;
        this.usedSize++;
    }
    public boolean isFull() {
        return this.usedSize == this.elem.length;
    }
//出栈
    public int pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        int oldValue = this.elem[usedSize-1];
        this.usedSize--;
        return oldValue;
    }
 //出栈
    public int peek() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空");
        }
        return this.usedSize--;
    }
}

主函数及其实现

    public static void main(String[] args) {
        MyStack stack = new MyStack();
        stack.push(12);
        stack.push(13);
        stack.push(14);
        stack.push(15);

        stack.push(16);
        stack.push(17);
        System.out.println(stack);   //[12, 13, 14, 15]
        System.out.println(stack.pop());   //弹出栈顶元素,并删除  15
        System.out.println(stack); //[12, 13, 14]

        System.out.println(stack.peek());   //弹出栈顶元素,不删除  15
        System.out.println(stack); //[12, 13, 14]
        System.out.println(stack.isEmpty());  //查询是否为空   false
    }

2.链表实现:头尾皆可实现

面试题1:有效字符串的实现

解析:1.左括号入栈, 若遇有括号看是否匹配peek()==[i]
     2.若匹配,则出栈;
     3.当遍历完字符串栈不为空,则组括号多,反之有括号多
  public boolean isValid(String s) {
        Stack<Character> stack = new Stack<>();  //给定一个栈用来存放字符
        for (int i = 0; i < s.length(); i++) {
            char ch = s.charAt(i);  //将字符串s转换为字符
            if (ch == '(' || ch == '[' || ch =='{') {  //判断是否为左括号,是的话写入栈
                stack.push(ch);
            }else {  //遇到右括号  查看匹配
                if (stack.empty()) {
                    System.out.println("右括号多");
                    return false;
                }
                char top = stack.peek();  //获取栈顶元素 是否有与之对应的括号  哪个左括号
                if (top == '{' && ch =='}' || top == '[' && ch ==']' ||
                    top == '(' && ch ==')') {
                    stack.pop();
                }else {
                    System.out.println("左右括号不匹配");
                    return false;
                }
            }
        }
        if (!stack.empty()) {
            System.out.println("左括号多");
            return false;
        }
        return true;
    }

面试题2:输入两个序列,第一个int[] pushA表示栈的压入顺序,判断第二个序列int[] poppA是否为弹出序列。

解析:1.遍历第一个序列pushA,将其放入栈里,直到第二个序列的首元素与第一个序列重元素相同,则弹出该元素,j++


    public boolean validateStackSequences(int[] pushA, int[] popA) {
        Stack<Integer> stack = new Stack<>();
        int j = 0;  //遍历popA
        for (int i = 0; i < pushA.length; i++) {
            stack.push(pushA[i]);
            //先判断写入stack栈里的元素是否等于压出序列的元素stack.peek() == popA[j]
            while (j < popA.length && !stack.empty() && stack.peek() == popA[j]) {
                stack.pop();  //弹出元素
                j++;
            }
        }
        return stack.empty();
    }

面试题3:根据 逆波兰表示法(后缀表达式),求表达式的值

也即是:(5+4)*3-2------>54+3*2-

解析:1.将常量放入栈中,遇到运算符则取出常量,进行运算并将结果放入栈中,继续此过程(遍历表达式找常量放入栈里),完成后缀表达式的计算

    public  int evalPRN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();  //new 一个stack用于存放整数
        for (int i = 0; i < tokens.length; i++) {
            String val = tokens[i];  //获取元素
            if (!isOperatation(val)) { //判断是否是运算符,不是要放入栈里stack.push(val)
                stack.push(Integer.parseInt(val));  //不是运算符 ,需要将字符串val转化为整型integer
            }else {   //确定是什么运算符
                int num2 = stack.pop();
                int num1 = stack.pop();
                switch (val) {
                    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 isOperatation(String x) {
        if (x.equals("+") || x.equals("-") || x.equals("*") || x.equals("/")) { //判断是否是运算符的条件
            return true;
        }
        return  false;
    }

面试题4:设计一个支持 push ,pop ,top 操作,并在常数时间内检索到最小元素的栈。

public class MinStack {

    private Stack<Integer> stack;
    private Stack<Integer> minStack;

    public MinStack() {  //构造方法
        stack = new Stack<>();  //初始化
        minStack = new Stack<>();
    }
    public void push(int val) {
        stack.push(val);  //普通栈放入元素--》最小栈则需要先看其是否为空
        if (!minStack.empty()) {  //不为空 获取最小栈的栈顶元素,与普通栈的元素val进行比较
            int top = minStack.peek();   //,val<=最小栈栈顶元素top 则将val其放入最小栈
            if(val <= top) {
                minStack.push(val);  //val更小时,则将其放入最小栈
            }
        }else {   //最小栈为空,执行元素放入最小栈
            minStack.push(val);
        }
    }
//出栈
    public void pop() {
        int popVal = stack.pop();  //保存普通栈弹出的元素
        if (!minStack.empty()) {
            int top = minStack.peek();  // 先获取最小栈栈顶的值
            if (top == popVal) {     //最小栈栈顶值top与普通栈出站的值进行比较
                minStack.pop();  //若相等,最小栈栈顶值top则也需要出栈,不等则无需进行操作
            }
        }
    }

    public int top() {
        return stack.peek();
    }
    public int getMin() {
        return minStack.peek();
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值