数据结构之栈

我们都知道栈是一种比较重要的数据结构然而他重要在哪呢?有何用处?如何设计我们自己的栈?本章将会探究解开栈的神秘面纱。

本文要点

在这里插入图片描述

了解栈

1 概念:

一种后进先出(LIFO)的数据结构,属于线性数据结构。

2 特点:

其实相对于数组来说栈操作的是数组的子集。只需要对数组添加约束便形成栈的特有功能。

添加约束:
1 规定只能向栈的末尾添加元素
2 规定只能从栈的末尾(栈顶)取出元素

ps:通过以上我们可以知道本文探讨的栈,底层还是用数组实现的(动态通用数组封装),如果不了解动态数组可以参考:https://blog.csdn.net/qq_38350635/article/details/86744319

3 常见应用栗子:
  • undo操作
    操作一步就把这一步入栈
  • 程序调用使用的系统栈
    使用系统栈记录程序的调用过程中断的点入栈
  • 括号匹配 (本节实现)

设计栈

通过以上我们知道了栈的特点后进先出,因此有关栈也有一些api:

在这里插入图片描述

因此我们结合动态数组设计我们自己的栈,看看栈到底是如何实现的。

1 首先设计接口(注意Stack为我们自定义不是java util包下的)

package stack;

/**
 * Create by SunnyDay on 2019/02/05
 * <p>
 * 自定义栈(与java api 中util包中stack栈同名)
 */
public interface Stack<E> {
    /**
     * 元素入栈
     */
    void push(E e);

    /**
     * 元素出栈
     */
    E pop();

    /**
     * 查看栈顶元素   有的使用 top命名 本处使用 peek
     * */
    E peek();

    /**
     * 栈中元素个数
     * */
    int getSize();

    /**
     * 栈 是否为空
     * */
    boolean isEmpty();
}

2 实现自定义栈ArrayStack

package stack;

import array.UseGeneric;

/**
 * Create by SunnyDay on 2019/02/05
 *
 * 基于通用动态数组实现
 */
public class ArrayStack<E> implements Stack<E> {
    private UseGeneric<E> array;// 成员  动态数组对象引用

    // 构造
    public ArrayStack(int capacity){
          array = new UseGeneric<>(capacity);
    }
    public ArrayStack(){
        array = new UseGeneric<>();
    }

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

     /**
      * 元素入栈
      * */
     @Override
     public void push(E e){
         //入栈就是把元素添加到栈的末尾
       array.addLast(e);
     }


   /**
    * 元素出栈
    * */
    @Override
    public E pop() {
        // 出栈 把当前的元素(栈的顶端栈顶)删除
        return array.removeLast();
    }

    /**
     * 查看栈顶元素(最后一个索引对应元素)
     * */
    @Override
    public E peek() {
        return array.getLast();
    }

    @Override
    public int getSize() {
        return array.getSize();
    }

    @Override
    public boolean isEmpty() {
        return array.isEmpty();
    }


    /**
     *
     * 栈  toString 特有
     * */
    @Override
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append("Stack: ");
        sb.append("[");
        for (int i = 0; i < array.getSize(); i++) {
            sb.append(array.get(i));
            if (i!=array.getSize()-1){
                sb.append(", ");
            }
        }
        sb.append("] :StackTop");
        return sb.toString();
    }
}

嗯?仅仅简单的两步就实现了我们自己的栈?这么简单哈哈,其实这主要是运用我们上一文章动态数组,简单封装就行就完事了。吧动态数组与栈的概念结合,就这么简单的完成了。不错我可以自信的对你说,经过一番探讨你读java自己stack的源码便easy多了哈哈。

栈代码实战

学过算法的同学应该练习过一道题“括号匹配”,接下来我们就实战下。

题目来源:
https://leetcode.com/problems/valid-parentheses/
(没错题目来源自大名鼎鼎的leetcode网站,练习题20,没看过的可以先读下题目)

1 首先我们进行分析

假如给了我们字符创 s ="([{}])" ,我们可以遍历字符,把字符左( 左 { 左[ 入栈 ,当遍历到右面的字符时拿来与栈顶作对比判断是否匹配(参看下图)
在这里插入图片描述

Talk is cheap show me code 哈哈
 public boolean isValid(String s) {
        // 此处使用java util 包下的Stack 类实现算法,方便我们提交
        ArrayStack<Character> stack = new ArrayStack<>();
        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;
                }
                char topC = stack.pop();
                if (c == ')' && topC != '(') {
                    return false;
                }
                if (c == ']' && topC != '[') {
                    return false;
                }
                if (c == '}' && topC != '{') {
                    return false;
                }

            }
        }
        // 栈空有效(入栈元素都匹配出栈)
        return stack.isEmpty();
    }

小结

栈虽是一种相对简单的数据结构,但是栈的应用还是满可以的。有时我们可能碰见问题但是想不到使用,还需要多练啊。

The end

笔冢研穿 任重道远 我们共同努力!!!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值