数据结构-Stacks

一 概念描述

1 栈是一种线性的数据结构;
2 相比数组栈操作的是数组的子集;
3 只能从一端添加元素也只能从一端取出元素(这一段成为栈顶);
4 栈在计算机世界里对于组件逻辑有非常重要的作用;

二 Stack

1、入栈
入栈图示
2、出栈
出栈图示

通过对比可以看出栈是一种后进先出的数据结构;也就是Last In Frist Out,缩写为LIFO;

三 栈相关的应用场景

1、无处不在的Undo操作(撤销);
2、程序调用所使用的系统栈;
public class Main {
    public static void main(String[] args) {
        funA();
    }

    public static void funA(){
        System.out.println("funA()开始执行");
        funB();
        System.out.println("funA()执行完毕");
    }

    public static void funB(){
        System.out.println("funB()开始执行");
        funC();
        System.out.println("funB()执行完毕");
    }

    public static void funC(){
        System.out.println("funC()开始执行");
        System.out.println("funC()");
        System.out.println("funC()执行完毕");
    }
测试代码执行结果
测试代码执行过程图示
测试代码执行过程入栈操作图示

测试代码执行过程出栈操作图示

通过以上图示可以看出,系统栈对于程序的子过程调用非常重要,它可以记录上一次调用的点,当程序执行完成一个子过程后通过这个记录可以快速的找到上一次未完成的操作继续执行;深入研究这个逻辑的话可以帮助我们更好的理解递归的操作;

四 栈的基本实现

4.1 栈的基本方法
Void push(E)  // 入栈

E pop()  // 出栈

E peek()  // 查看栈顶元素

Int getSize() // 查看栈一共有多少元素

Boolean isEmpty() // 查看栈是否为空

其实从用户的角度去看,支持这些操作就可以满足日常的需求,具体的底层实现,用户是不会去关心的,实现底层有多种方式;

4.2 栈的底层实现(数组实现)
package com.mufeng.stacks;

/**
 * @author wb-yxk397023
 * @date 2018/6/7 20:42
 */
// 定义Stack接口
public interface Stack {
    /**
     * 获取栈的长度
     * @return
     */
    int getSize();

    /**
     * 查看栈是否为空
     * @return
     */
    boolean isEmpty();

    /**
     * 入栈
     * @param e
     */
    void push(E e);

    /**
     * 出栈
     * @return
     */
    E pop();

    /**
     * 查看栈顶元素
     * @return
     */
    E peek();
}
package com.mufeng.stacks;

import com.mufeng.arrays.Array;

/**
 * Created by wb-yxk397023 on 2018/6/9.
 */
// Stack实现类
public class ArrayStack implements Stack {

    /**
     * 引入数组
     */
    private Array array;

    /**
     * ArrayStack有参构造器
     * @param capacity
     */
    public ArrayStack(int capacity){
        array = new Array<>(capacity);
    }

    /**
     * ArrayStack无参构造器
     */
    public ArrayStack(){
        array = new Array<>();
    }

    /**
     * 获取栈中元素的个数
     * @return
     */
    @Override
    public int getSize() {
        return array.getSize();
    }

    /**
     * 判断栈是否为空
     * @return
     */
    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }

    /**
     * 向栈中添加一个元素
     * @param e
     */
    @Override
    public void push(E e) {
        array.addLast(e);
    }

    /**
     * 出栈
     * @return
     */
    @Override
    public E pop() {
        return array.removeLast();
    }

    /**
     * 查看栈顶元素
     * @return
     */
    @Override
    public E peek() {
        return array.getLast();
    }

    /**
     * 获取栈的容量
     * @return
     */
    public int getCapacity(){
        return array.getCapacity();
    }

    /**
     * 重写toString
     * @return
     */
    @Override
    public String toString(){
        StringBuilder res = new StringBuilder();
        res.append("Stack: ");
        res.append('[');
        for (int i = 0; i < array.getSize(); i++){
            res.append(array.get(i));
            if (i != array.getSize() - 1){
                res.append(", ");
            }
        }
        res.append("] top");
        return res.toString();
    }
}
package com.mufeng;

import com.mufeng.stacks.ArrayStack;
// 测试Stack
public class Main {

    public static void main(String[] args) {
        ArrayStack eArrayStack = new ArrayStack<>();

        for (int i = 0; i < 5; i++){
            eArrayStack.push(i);
            System.out.println(eArrayStack);
        }

        eArrayStack.pop();
        System.out.println(eArrayStack);
    }
}
测试结果

五 栈的另一个应用(括号匹配练习)

5.1 假设一个算术表达式中可以包含三种括号:圆括号“(”和“)”,方括号“[”和“]”和花括号“{”和“ ”,且这三种括号可按任意的次序嵌套使用(如:…[…{… …[…]…]…[…]…(…)…)。编写判别给定表达式中所含括号是否正确配对出现的算法。输出结果True 或者 False。
5.2 代码实现
package com.mufeng.stacks;

import java.util.Stack;

/**
 * Created by wb-yxk397023 on 2018/6/9.
 */
// 括号匹配
public class Solution {

    public boolean isValid(String s){

        Stack stack = new Stack<>();

        for (int i = 0; i < s.length(); i++){
            char c = s.charAt(i);

            if (c == '(' || c == '[' || c == '{'){
                stack.push(c);
            }else {
                if (stack.isEmpty()){
                    return false;
                }

                Character popChar = stack.pop();

                if (c == ')' && popChar != '('){
                    return false;
                }
                if (c == ']' && popChar != '['){
                    return false;
                }
                if (c == '}' && popChar != '{'){
                    return false;
                }
            }
        }

        return stack.isEmpty();
    }

    public static void main(String[] args){
        System.out.println((new Solution()).isValid("()[]{}"));
        System.out.println((new Solution().isValid("([)]")));
    }
}
测试结果图示
5.3 原理解析
1.png

1⃣️ 首先需要一个空的栈来接收传来的字符;


2.png

2⃣️ 依次检查传来的字符是否为括号的左半部分,如果是则放入栈中;


3.png

3⃣️ 拿到字符串中括号的右半部分于栈中的已有的字符进行判断,如果是左右对称的则将栈中的字符弹出;等到栈中所有的字符都匹配完成会返回结果,此实例的结果为true;
这是一个错误的实例

4⃣️ 这个实例将无法得到匹配,结果为false;
5.4 括号匹配总结:栈顶元素反映了在嵌套的层次关系中,最近的需要匹配的元素;

你可能感兴趣的:(数据结构-Stacks)