美文网首页
第四讲-栈

第四讲-栈

作者: 小妍妍说 | 来源:发表于2018-12-19 20:31 被阅读0次

栈的特点是先进后出,后进先出

栈只允许在一端插入和删除数据。

如何实现一个“栈”?

栈主要包括两个操作:入栈or出栈

顺序栈和链式栈

实际上,栈既可以用数组来实现,也可以用链表来实现。

用数组实现的栈,我们叫作顺序栈,用链表实现的栈,我们叫作链式栈。

用数组实现栈:

// 基于数组实现的顺序栈
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)。

栈的时间复杂度:

​ 不管是顺序栈还是链式栈,入栈、出栈只涉及栈顶个别数据的操作,所以时间复杂度都是 O(1)。

支持动态扩容的栈

基于数组的顺序栈往往是一个固定大小的栈,如若想要其支持动态扩容,只需底层依赖一个支持动态扩容的数组就可以了。

支持动态扩容的时间复杂度:

​ 入栈:若有空闲空间,则复杂度为 O(1);若需扩容则涉及到数据的copy迁移,则复杂度为 O(n)。

​ 出栈: O(1)。

栈的应用:

(1)函数调用栈:操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构, 用来存储函数调用时的临时变量。

​ 解:每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完成,返回之后,将这个函数对应的栈帧出栈。

函数调用栈代码:

int main() {
   int a = 1; 
   int ret = 0;
   int res = 0;
   ret = add(3, 5);
   res = a + ret;
   printf("%d", res);
   reuturn 0;
}

int add(int x, int y) {
   int sum = 0;
   sum = x + y;
   return sum;
}

(2)表达式求值:求3+5*8-6的值

​ 编译器就是通过两个栈来实现的。其中一个保存操作数的栈,另一个是保存运算符的栈。

​ 解:从左向右遍历表达式,当遇到数字,直接压入操作数栈;当遇到运算符,就与运算符栈的栈顶元素进行比较。如果比运算符栈顶元素的优先级高,就将当前运算符压入栈;如果比运算符栈顶元素的优先级低或者相同,从运算符栈中取栈顶运算符,从操作数栈的栈顶取 2 个操作数,然后进行计算,再把计算完的结果压入操作数栈,继续比较。

如图解:

1545221903402.png

(3)括号匹配问题:

​ 假设表达式中只包含三种括号,圆括号 ()、方括号 [] 和花括号{},并且它们可以任意嵌套。比如,{[{}]}或 [{()}([])] 等都为合法格式,而{[}()] 或 [({)] 为不合法的格式。有一个包含三种括号的表达式字符串,如何检查它是否合法呢?

​ 解:用栈来保存未匹配的左括号,从左到右依次扫描字符串。当扫描到左括号时,则将其压入栈中;当扫描到右括号时,从栈顶取出一个左括号。如果能够匹配,比如“(”跟“)”匹配,“[”跟“]”匹配,“{”跟“}”匹配,则继续扫描剩下的字符串。如果扫描的过程中,遇到不能配对的右括号,或者栈中没有数据,则说明为非法格式。当所有的括号都扫描完成之后,如果栈为空,则说明字符串为合法格式;否则,说明有未匹配的左括号,为非法格式。

(4)浏览器的前进后退问题

​ 使用两个栈,X 和 Y,我们把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈 X 中出栈,并将出栈的数据依次放入栈 Y。当我们点击前进按钮时,我们依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。

相关文章

  • 第四讲-栈

    栈的特点是先进后出,后进先出。 栈只允许在一端插入和删除数据。 如何实现一个“栈”? 栈主要包括两个操作:入栈or...

  • SLAM前端 - 直接法

    参考:高翔——《视觉SLAM十四讲》第8讲 视觉里程计2高翔——《视觉SLAM十四讲》系列讲解视频及PPT ch8...

  • SLAM前端 - 相机运动估计 & 特征点位置估计

    参考:高翔——《视觉SLAM十四讲》第7讲 视觉里程计1高翔——《视觉SLAM十四讲》系列讲解视频及PPT ch7...

  • 数据结构的各种代码

    第 02 章 线性表 顺序存储结构 链式存储结构 第 03 章 栈与队列 顺序栈 链栈 两栈共享空间 循环队列 链...

  • 2021-05-09

    2021年共读第10本 【穷查理宝典】共读第19天 1摘要: 第四讲 跨学科思维

  • LeetCode-20 有效的括号

    题目:20. 有效的括号 难度:简单 分类:栈 解决方案:入栈出栈 今天我们学习第20题有效的括号,这是一道关于栈...

  • Aha! Algorithms - Stack

    《啊哈!算法》第 2 章第 2 节,栈的 Swift 实现。 问题 判断字符串是否回文 解决 将字符串前半部分入栈...

  • 籽林读书笔记《品味四讲》

    《品味四讲》蒋勋 第1天,年初九,2019.2.13 第8~27P“生活美学的起点” 回到大自然,回到生活本身,发...

  • SLAM前端 - 特征检测与匹配

    参考:高翔——《视觉SLAM十四讲》第7讲 视觉里程计1知乎zhixin yan——Visual SLAM前端技术...

  • 林祺堂老师叙事第四讲——从独特意义经验到故事改写

    中原焦点解决团队高级五期 讲师第13期 贺变丽 坚持分享第1296天 2021—12—31 林老师第四讲主...

网友评论

      本文标题:第四讲-栈

      本文链接:https://www.haomeiwen.com/subject/nfsskqtx.html