漫谈数据结构——栈

125 阅读2分钟

这是我参与2022首次更文挑战的第29天,活动详情查看:2022首次更文挑战

前言

今天我们来继续讨论一个新的数据结构,就是栈,它的基本定义就是后进先出,只有一端在增加和删除数据,栈的数据结构适用于特定场景,它可以使用我们之前的讨论过的数组或者链表进行实现。

栈的特定场景

在计算机的组成部分里,与CPU交互的其中的一个寄存器就是%rsp,它是一个栈指针的寄存器,使用专门的指令push和pop进行操作的。那么栈具有的元素操作的功能,数组也有,链表也有。那为什么还要使用栈呢?首先在我们平时编码的对象设计中,每个对象其实都可以转换为HashMap,为什么还要那么多对象呢。我们设计系统的目的,首先层次要清晰,每个对象负责对应的场景,每个对象具有特定场景下的功能,如果超脱了这个限定范围,这个对象就不再适用了,其次每个对象的封装,简化了上层使用的逻辑性,以及隐藏了底层使用的复杂性,让对象更易用,并且让开发者更专注核心逻辑的编写。栈和数组也是相同的性质,栈把数组的作用范围缩小,功能缩减,灵活性降低,让栈只适应于它的特定场景。那么它有什么适用场景呢?

四则运算

四则运算的现实逻辑描述,非常符合栈的特性,我们可以使用两个栈来实现一个简单的四则运算的计算器。首先可以定义四则运算的优先级,乘除的优先级肯定最高,而加减的优先级肯定是最低的。然后定义两个栈分别是:数字栈和运算符栈,当遇到数字时,我们把数字压入数字栈中,当遇到运算符时,我们可以跟栈顶的运算符进行比较,如果栈顶的运算符优先级大于或者与当前运算符统计,那么我们就可以从数字栈中弹出两个数字,进行运算后,再将结果压入栈中。这样一个简单的四则计算器就实现了,下面我提供一个Java的实现代码:

public class Solution {

    Map<Character, Integer> map = new HashMap<Character, Integer>(){{
        put('-', 1);
        put('+', 1);
        put('*', 2);
        put('/', 2);
    }};
    public int calculate(String s) {
        s = s.replaceAll(" ", "");
        Deque<Integer> nums = new ArrayDeque<>();
        nums.add(0);
        Deque<Character> operators = new ArrayDeque<>();
        char[] chars = s.toCharArray();
        for (int i = 0; i < chars.length; i++) {
            char character = chars[i];
            if (Character.isDigit(character)) {
                int j = i;
                int sum = 0;
                while (j < chars.length && Character.isDigit(chars[j])) {
                    sum = sum * 10 + (chars[j] - '0');
                    j++;
                }
                nums.addLast(sum);
                i = j - 1;
            } else {

                while (!operators.isEmpty()) {
                    char prev = operators.peekLast();
                    if (map.get(prev) >= map.get(character)) {
                        calc(nums, operators);
                    } else {
                        break;
                    }
                }

                operators.addLast(character);
            }
        }

        while (!operators.isEmpty()) {
            calc(nums, operators);
        }

        return nums.peekLast();
    }

    private void calc(Deque<Integer> nums, Deque<Character> operators) {
        if (nums.isEmpty() || nums.size() < 2) {
            return;
        }
        if (operators.isEmpty()) {
            return;
        }

        Integer b = nums.pollLast();
        Integer a = nums.pollLast();
        Character pop = operators.pollLast();
        switch (pop) {
            case '+':
                nums.addLast(a + b);
                break;
            case '-':
                nums.addLast(a - b);
                break;
            case '*':
                nums.addLast(a * b);
                break;
            default :
                nums.addLast(a / b);
                break;
        }

    }

总结

栈是一个简单清晰,但是功能的适用性也非常强大的数据结构的。