算法通关村第四关——理解栈

1.栈基础知识

1.1 栈的特征

栈和队列是比较特殊的线性表,又称之为访问受限的线性表。栈是很多表达式、符号等运算的基础,也是递归的底层实现。理论上递归能做的题目栈都可以,只是有些问题用栈会非常复杂。 栈底层实现仍然是链表或者顺序表,栈与线性表的最大区别是数据的存取的操作被限制了,其插入和删除操作只允许在线性表的一端进行。一般而言,把允许操作的一端称为栈顶(Top),不可操作的一端称为栈底(Bottom),同时把插入元素的操作称为入栈(Push),删除元素的操作称为出栈(Pop)。若栈中没有任何元素,则称为空栈

1.2栈的操作

栈的常用操作主要有:

  • push(E):增加一个元素E

  • pop():弹出元素E

  • peek():显示栈顶元素,但是不出栈

  • empty():判断栈是否为空

 

如果想测试一下自己对栈是否理解,做一下这道题就够了:**入栈顺序为1234,所有可能的出栈序列是什么?**

入栈顺序为1234的数字,出栈顺序有14种,10种不可能

以 1 先入栈并出栈 正确的序列:

1 2 3 4 -> 1先入栈再出栈,2入栈在出栈,3 入栈再出栈,4 入栈再出栈

1 2 4 3 -> 1先入栈再出栈,2入栈在出栈,3 入栈不出,4 入栈再出栈,最后 3 出栈

1 3 2 4 -> 1先入栈再出栈,2 入栈不出,3 入栈在出栈,2 再出栈,最后4 入栈出栈

1 3 4 2 -> 1先入栈再出栈,2 入栈不出,3 再入栈出栈,4 再入栈出栈,最后 2 出栈

1 4 3 2 -> 1先入栈再出栈,2 入栈不出,3 入栈不出,4 入栈出栈,最后出 3 2 栈

不可能的序列

1 4 2 3 -> 1先入栈再出栈,2 3 入栈不出,再出 4,发现 2 是出不了的,因为前面3没出

以 2 先入栈出栈

正确的序列:

2 1 3 4 -> 1入栈不出,2先入栈再出栈,出栈1,3 入栈出栈,4 入栈出栈

2 1 4 3 -> 1入栈不出,2先入栈再出栈,出栈1,3 入栈不出,4 入栈出栈,最后出栈3

2 3 4 1 -> 1入栈不出,2先入栈再出栈,3 入栈出栈,4 入栈出栈,最后出栈1

2 3 1 4 -> 1入栈不出,2先入栈再出栈,3 入栈出栈,再出栈1,最后4入栈出栈

2 4 3 1 -> 1入栈不出,2先入栈再出栈,3 入栈不出,4 入栈出栈,再出栈3,最后出栈1

不可能的序列 2 4 1 3 -> 1入栈不出,2先入栈再出栈,3 入栈不出,4 入栈出栈,1出不了,前有3

以 3 先入栈出栈

正确的序列:

3 2 1 4 -> 1入栈不出,2入栈不出,3 入栈出栈,再 2 1 出栈,最后 4入栈出栈

3 2 4 1 -> 1入栈不出,2入栈不出,3 入栈出栈,出栈2,4入栈出栈,最后出栈1

3 4 2 1 -> 1入栈不出,2入栈不出,3 入栈出栈,4 入栈出栈,2 1 出栈

不可能的序列

3 4 1 2 -> 1入栈不出,2入栈不出,3 入栈出栈,4 入栈出栈,1 是出不了的,前面有2

3 1 2 4 -> 1入栈不出,2入栈不出,3 入栈出栈,1 是出不了的,前面有2

3 1 4 2 -> 1入栈不出,2入栈不出,3 入栈出栈,1 是出不了的,前面有2

以 4 先入栈出栈

正确的序列:

4 3 2 1 -> 1入栈不出,2入栈不出,3 入栈不出,4 入栈不出,然后分别出 3 2 1

不可能的序列 4 3 1 2、4 2 1 3、4 2 3 1、4 1 3 2、4 1 2 3

2.基于数组实现栈

栈是一种先进后出的数据结构,需要注意 top有的地方指向栈顶元素,有的地方指向栈顶再往上的一个空单位。

这里是使用数组实现栈

入栈过程如下:

算法通关村第四关——理解栈_第1张图片

 出栈过程如下:

算法通关村第四关——理解栈_第2张图片

思路:定义一个全局的数组保存值,top 变量保存栈顶,默认初始化大小为 10

出栈:先进行判空操作,然后取出栈顶的元素,再删除栈顶的元素,size--,最后返回顶部元素。

入栈:先会进行扩容操作,如果当前数组的大小已经超出了,那么每次扩大 50%,然后给 顶部元素赋新值,最后 size++;

 

代码:

import java.util.Arrays;

public class MyStacks {
    // 栈中的数组
    public Object[] stack;

    //栈顶位置
    public int top;

    // 默认长度为 10
    public MyStacks() {
        stack = new Object[10];
    }

    public static void main(String[] args) {
        MyStacks stack = new MyStacks<>();
        stack.push("hello");
        stack.push("Java");

        stack.pop();

        System.out.println(stack.peek());
    }

    // 判断栈是否为空
    public boolean isEmpty() {
        return top == 0;
    }

    // 查看栈顶元素
    public T peek() {
        if (isEmpty()) {
            return null;
        }

        T t = (T) stack[top - 1];
        return t;
    }

    // 出栈
    public T pop() {
        if (isEmpty()) {
            return null;
        }

        // 获取栈顶元素
        T t = peek();

        // 删除栈顶元素
        stack[top-1] = null;
        top--;

        return t;
    }

    // 入栈
    public void push(T t) {
        expandCapacity(top+1);

        stack[top] =  t;
        top++;
    }

    //扩大容量
    public void expandCapacity(int size) {
        int len = stack.length;
        if (size > len) {
            size = size * 3 / 2 + 1;//每次扩大50%
            stack = Arrays.copyOf(stack, size);
        }
    }
}

 

你可能感兴趣的:(数据结构与算法,算法)