数据结构 - 栈

本文介绍了栈这种数据结构,从栈的定义、实现到实际应用的案例,通过判断字符串中小括号是否合法来阐述栈的后进先出特性。栈在解决特定问题时能简化思考过程,提供了解决问题的新思路。
摘要由CSDN通过智能技术生成

目录

前言

栈的定义

栈的实现

栈的应用练习


前言

 一直都觉得数据结构学了也不知道干什么用,直到最近学习了一下vue的源码,在vue的编译模板阶段,获取一组组标签就是通过栈实现的。所以有一些思考,当你对所谓的一些数据结构、基础算法完全不了解的时候,在遇到问题的时候就完全想不到有这样一个简单的方案解决。有点像内功,没法给你招式,不见得能在工作中大量使用,但是熟悉之后又会提高解决问题的能力,拓宽解决问题的思路。所以,虽然繁琐,学起来又无聊,但是多少还是学一学吧hhh

下面,数据结构的学习,就从先给我启发的栈开始吧。

栈的定义

栈是一种特殊的线性表,仅能在栈顶进行操作,有着后进先出、先进后出的特性。

某种意义上讲,它像是一个开口的盒子,先放进去的东西总是会被后放进去的东西压在下面,那么如果想拿出被压住的东西,必须要先取出顶部的东西,也就是后放进去的东西。放进去东西的过程叫压栈也就显得很贴切了。

网上找的显示栈工作特点的图:

栈的实现

我了解到栈是可以通过链表实现的,但是,,链表,,不知道是啥… 所以还是用数组实现了。

栈的实现如下:

  class Stack {
    constructor(){
      let items = [];
      // 压栈,其实就是数组后面加一个元素
      this.push = function (val) {
        items.push(val)
      }
      // 弹出栈顶元素
      this.pop = function () {
        return items.pop();
      }
      // top 方法返回栈顶元素
      this.top = function(){
        return items[items.length - 1];
      };
      // 判断是否为空
      this.isEmpty = function(){
        return !!items.length == 0;
      };
      // size 方法返回栈的大小
      this.size = function(){
        return items.length;
      };
      // clear 清空栈
      this.clear = function(){
        items = []
      };
    }
  }

栈的应用练习

看完之后是不是很失望??!这就对数组做了个封装啊,它能实现的数组也能实现啊,那我弄个栈有啥用啊还?!

说实话具体细节我也说不出来,但是我就是觉得,在栈的基础上思考问题会比在数组的基础上思考简单多了,不信我们来看看下面的练习。

练习题目

下面字符串中包含小括号,请写一个判断小括号是否合法成对出现。

sdf(ds(ew(we)rw)rwqq)qwewe
(sd(qwqw)sd(sd))
()()sd()(sd()fw))(

这个题目是在网上看到的,看vue解析模板的时候想到,vue获取成对的HTML标签的操作和这个题目的核心是一样的。下面就来思考一下如何解决。

思路分析

从字符串中可以看到,小括号不仅仅存在并列关系,而且存在嵌套关系,现在你用栈的思维思考一下,这个东西应该怎么处理,循环一下字符串,对每个字符进行如下操作

1、遇到左括号,压栈

2、遇到右括号,判断栈是否为空,如果为空证明没有左括号抵消,少个左括号,直接返回false,如果不为空,就把栈顶移除,这一对括号就抵消了

3、循环结束后,如果栈是空的,那就对了,说明所有括号都抵消了返回true,如果栈里还有,说明左括号多了,不合法返回false

代码示例

  function isIegitimate(str) {
    let stack = new Stack()
    for (let i=0;i<str.length;i++){
      let item = str[i]
      if (item=='('){
        // 判断到左括号,压栈
        stack.push(item)
      }else if (item==')') {
        // 判断为右括号且栈内为空,则说明左括号少了
        if (stack.isEmpty()){
          return false
        } else {
          // 不空则弹出上面的左括号,拿去配对
          stack.pop()
        }
      }
    }
    // 循环完了是不是空的,空的就对,不空就是左括号多了
    return stack.isEmpty()
  }

  console.log(isIegitimate('sdf(ds(ew(we)rw)rwqq)qwewe'));
  console.log(isIegitimate('(sd(qwqw)sd(sd))'));
  console.log(isIegitimate('()()sd()(sd()fw))('));

执行结果:

文章到这里就基本结束了,小小的总结一下,栈的核心思想就是后入先出,站在这个思维上,他是不是由数组实现的就不重要了,我们在思考问题的时候,省去了实现过程的思维,直接在栈的思维上思考,在某些时候会对我们有很大的帮助。

ps:突然想起前面的文章执行上下文和变量对象中说到函数调用栈的时候也有个调用栈的图,感兴趣的可以去看看~

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值