Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >白话文讲栈

白话文讲栈

作者头像
幺鹿
发布于 2019-04-18 08:48:58
发布于 2019-04-18 08:48:58
44000
代码可运行
举报
文章被收录于专栏:Java呓语Java呓语
运行总次数:0
代码可运行

思考题

给定一个仅包含字符:(,),[,]的字符串,确定输入字符串是否有效。 字符串有效的定义如下:

  • 开括号必须用同一类型的括号闭合。
  • 开方括号必须按正确顺序闭合。
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 示例1
Input: "()"
Output: true
// 示例2
Input: "()[]{}"
Output: true
// 示例3
Input: "(]"
Output: false

可以先思考一下这个问题,是否可以结合栈解决呢?

栈(stack)又名堆栈,它是一种操作受限的线性表。其限制是仅允许在线性表头进行插入和删除运算。这一端被称为栈顶,相对地,把另一端称为栈底。

  • 向一个栈插入新元素又称作进栈、入栈或压栈,它是把新元素放到栈顶元素的上面,使之成为新的栈顶元素;
  • 从一个栈删除元素又称作出栈、退栈或弹栈,它是把栈顶元素删掉,使下方的元素成为新的栈顶元素;

栈按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。

关于栈我列举一个很贴切的例子,就是一摞叠在一起的书。假设我们平时放书的时候,都是从下往上一本一本的放,取书的时候也都是从上往下一本一本的取,不能从中间任意位置抽取和放置,这就是典型的栈结构。

一叠书.png

如何实现栈呢?

前面我们讲解过数组和链表,栈也可以使用这两个数据结构去实现。基于数组实现的栈,我们称之为数组栈。基于链表实现的栈,我们称之为链式栈。由于数组的特性,数组栈的空间是有界的,当栈的空间不满足需求时,需要执行扩容。而链表理论上则是无界的,因为实际受到物理资源限制。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
// 基于数组实现的顺序栈
public class ArrayStack {
  private String[] items;  // 数组
  private int count;       // 栈中元素个数
  private int n;           // 栈的大小

  // 初始化数组,申请一个大小为 n 的数组空间
  public ArrayStack(int n) {
    this.items = new String[n];
    this.n = n;
    this.count = 0;
  }

  // 入栈操作
  public boolean push(String item) {
    // 数组空间不够了,直接返回 false,入栈失败。
    if (count == n) return false;
    // 将 item 放到下标为 count 的位置,并且 count 加一
    items[count] = item;
    ++count;
    return true;
  }
  
  // 出栈操作
  public String pop() {
    // 栈为空,则直接返回 null
    if (count == 0) return null;
    // 返回下标为 count-1 的数组元素,并且栈中元素个数 count 减一
    String tmp = items[count-1];
    --count;
    return tmp;
  }
}

了解了定义和基本操作,那它的操作的时间、空间复杂度是多少呢?

不管是顺序栈还是链式栈,我们存储数据只需要一个大小为 n 的数组就够了。在入栈和出栈过程中,只需要一两个临时变量存储空间,所以空间复杂度是 O(1)。

注意,这里存储数据需要一个大小为 n 的数组,并不是说空间复杂度就是 O(n)。因为,这 n 个空间是必须的,无法省掉。所以我们说空间复杂度的时候,是指除了原本的数据存储空间外,算法运行还需要额外的存储空间。

空间复杂度分析是不是很简单?时间复杂度也不难。不管是顺序栈还是链式栈,入栈、出栈只涉及栈顶个别数据的操作,所以时间复杂度都是 O(1)。

Java中的栈的实现

Java中的栈我们主要关注Stack类,它继承自VectorVector是线程安全容器,但由于使用synchronized锁,在要求高性能高并发环境下并不推荐。

Stack使用数组存储元素,但凡使用数组构建的数据结构都会有一个共通的问题——需要扩容。在JDK8中,默认情况下Stack的扩容规则是当栈的大小等于容量大小时,则将当前容量扩大为现在容量的两倍。如果要修改默认扩容行为,可以通过构造器设定扩容的步长,以求更合理的配置扩容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
Object (java.lang)
       AbstractCollection (java.util)
              AbstractList (java.util)
                     Vector (java.util)
                            Stack (java.util)

解答思考题

使用栈这种数据结构,使得我们很容易解决诸如逆波兰式汉诺塔等问题。熟悉栈的定义并不难,但我们对栈的理解不能仅仅停留在静态栈的层面上,更多的需要思考栈的动态性,结合这些动态性我们可以解决哪些问题。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    public boolean isValid(String s) {

        if ((s.length() & 1) == 1) {
            return false;
        }

        HashMap<Character, Character> symbolMap = new HashMap<>();
        symbolMap.put(')', '(');
        symbolMap.put('}', '{');
        symbolMap.put(']', '[');

        Stack<Character> stack = new Stack<>();

        for (int i = 0; i < s.length(); i++) {
            char c = s.charAt(i);
            switch (c) {
                case ')':
                case '}':
                case ']':
                    if (stack.empty()) {
                        return false;
                    } else if (Objects.equals(stack.lastElement(), symbolMap.get(c))) {
                        stack.pop();
                    } else {
                        stack.push(c);
                    }
                    break;
                default:
                    stack.push(c);
                    break;
            }
        }
        return stack.empty();
    }
}
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019.04.10 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
什么是栈?
本文将介绍一个重要的数据结构—栈,和之前讲到的链表、数组一样也是一种数据呈线性排列的数据结构,不过在这种结构中,我们只能访问最新添加的数据。栈就像是一摞书,拿到新书时我们会把它放在书堆的最上面,取书时也只能从最上面的新书开始取。
武培轩
2020/02/12
4560
三分钟基础知识:什么是栈?
对于栈的认识,相信每个学习数据结构的小伙伴多多少少有一定的认识和了解。很多刚刚学习的小伙伴说学习数据结构在实际中没怎么见到应用,那是因为你没有去仔细的观察,而且像栈这常用到的数据结构通常会使用在实际开发中,比如:表达式的运算、花括号的匹配以及浏览器的前进后退等等很多。
帅地
2019/10/23
2K0
三分钟基础知识:什么是栈?
算法之旅:栈
前面我们聊到数组:面试中的疑难点与链表:由浅入深,今天我们继续另外一种数据结构:栈。
Rouse
2021/02/23
2530
算法之旅:栈
8.栈实现浏览器的前进后退
当你一次访问 1、2、3 页面之后,点击浏览器的后退按钮就可以返回到 2 和 1.当后退到 1,点击前进按钮还可以继续查看页面 2、3。但是当你退到 2 页面,点击了新的页面 4,那就无法继续通过前进、后退查看页面 3 了。
码哥字节
2020/05/01
1.4K0
重学数据结构和算法(一)之复杂度、数组、链表、栈、队列、图
最近学习了极客时间的《数据结构与算法之美]》很有收获,记录总结一下。 欢迎学习老师的专栏:数据结构与算法之美 代码地址:https://github.com/peiniwan/Arithmetic
六月的雨
2021/03/02
6040
重学数据结构和算法(一)之复杂度、数组、链表、栈、队列、图
关于 “栈” 的那点破事
用生活中最实际的例子来说,类似于砌砖,加入我们要砌一堵墙,我们肯定是从下往上砌,先拿的砖头就砌在最下边,后拿的砖头就砌到最上边。但是如果监工觉得这堵墙不合适,我们就需要把这堵墙拆了重砌,这时候我们需要先把上面的砖先取掉,才能取下面的砖。而这种先进后出,后进先出的结构就叫做 “栈”。
村雨遥
2020/09/11
5310
【Java数据结构】详解Stack与Queue(一)
由于顺序栈是由顺序存储实现的,所以其底层是一个动态数组 。以下是其模拟实现的代码。
E绵绵
2024/06/04
1120
【Java数据结构】详解Stack与Queue(一)
数据结构-栈结构
有一个非常贴切的例子,就是一摞叠在一起的盘子。我们平时放盘子的时候,都是从下往上一个一个放;取的时候,我们也是从上往下一个一个地依次取,不能从中间任意抽出。后进者先出,先进者后出,这就是典型的“栈”结构。
acc8226
2022/05/17
4280
数据结构-栈结构
LeetCode题解—实现一个栈
主要就是将对栈的几个方法转化成对数组的处理,比如入栈就是添加数组数据,出栈就是返回数组最后一个数据。
码上积木
2021/03/10
5700
java数据结构之(顺序栈+链式栈)
今天介绍一下数据结构中的栈。栈实现和线性表实现差不多都是有两种实现方式,一种是顺序栈,另一种就是链式栈。
林老师带你学编程
2022/11/30
4350
适合特定场景。从功能上说,数组或者链表都可以替代栈,但是,因为特定的数据结构是对特定场景的抽象,而且数组或者链表暴露了太多的操作接口,操作上确实灵活自由,但是,使用时比较不可控,容易出错。
Vincent-yuan
2020/05/08
5910
如何用栈实现浏览器的前进和后退?
这里先介绍一下栈的定义和实现,并介绍它的一些常用的应用,最后再简单实现一个简单的浏览器前进和后退的操作。
kbsc13
2019/11/08
9760
图解 | 不就是栈吗
栈(stack)是一种先进后出,后出先进的数据结构。之所以这样,是因为栈是操作受限的线性表,允许元素进出的一端称为栈顶(top),不允许元素进出的一端称为栈底(bottom)。
五分钟学算法
2021/03/10
6650
Java数据结构与算法解析(二)——栈
栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶。对栈的基本操作有push(进栈)和pop(出栈),对空栈进行push和pop,一般被认为栈ADT的一个错误。当push时空间用尽是一个实现限制,而不是ADT错误。栈有时又叫做LIFO(后进先出)表。
老马的编程之旅
2022/06/22
3250
Java数据结构与算法解析(二)——栈
重学数据结构(二、栈)
比如上面的羽毛球筒,只能将最顶端的羽毛球移出,也只能将新的羽毛球放到最顶端——这两种操作分别称作入栈( Push)和出栈( Pop)。入栈和出栈的示意图如下:
三分恶
2020/08/30
3750
数据结构与算法之栈
栈是一种操作受限的数据结构,只支持入栈和出栈操作。 典型的“栈”结构:后进者先出,先进者后出。 从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。 特定的数据结构是对特定场景的抽象,而且,数组或链表暴露了太多的操作接口,操作上的确灵活自由,但使用时就比较不可控,自然也就更容易出错。 二、如何实现一个“栈”?
袁新栋-jeff.yuan
2020/08/26
4210
数据结构与算法学习笔记之后进先出的“桶”
1.“后进先出,先进后出”的数据结构。 2.从操作特性来看,是一种“操作受限”的线性表,只可以在一端插入和删除数据。
Dawnzhang
2018/10/18
4240
数据结构与算法学习笔记之后进先出的“桶”
栈的深度解析:顺序栈与链栈的实现
栈是一种重要的线性数据结构,遵循“后进先出”(LIFO)的原则。栈的应用非常广泛,如表达式求值、括号匹配、递归实现等。在本文中,我们将深入探讨栈的概念,并通过顺序栈和链栈两种实现方式进行对比分析。
平凡之路.
2024/10/09
6930
栈的深度解析:顺序栈与链栈的实现
数据结构与算法 --- 组数、链表、栈和队列(二)
继数据结构与算法 --- 组数、链表、栈和队列(一)讲解完数组,链表及算法的优化策略之后,接下来继续讲解「两种特殊的线性表结构,栈和队列」。
Niuery Diary
2023/10/22
2690
数据结构与算法 --- 组数、链表、栈和队列(二)
【愚公系列】2023年11月 数据结构(四)-栈
数据结构是计算机科学中的一个重要概念,它描述了数据之间的组织方式和关系,以及对这些数据的访问和操作。常见的数据结构有:数组、链表、栈、队列、哈希表、树、堆和图。
愚公搬代码
2023/11/03
2440
相关推荐
什么是栈?
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验