数据结构与算法之美 | 学习笔记05 —— 栈

一、栈

定义:当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们就应该首选“”这种数据结构。
用数组实现的栈,叫顺序栈;用链表实现的栈,叫链式栈。
顺序栈的实现

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

计算空间复杂度时,是指除了原本的数据存储空间外,算法运行还需要额外的存储空间。因此,此操作的空间复杂度为 O ( 1 ) O(1) O(1),时间复杂度为 O ( 1 ) O(1) O(1)

二、栈的动态扩容

当栈满后需要动态扩容,申请一块更大的内存,再将原来的数据搬移到新数组中。栈的动态扩容

动态扩容的时间复杂度分析

出栈 O ( 1 ) O(1) O(1)
入栈

  • 当栈有空闲空间时,入栈操作的时间复杂度为 O ( 1 ) O(1) O(1),为最好时间复杂度;
  • 当空间不够时,要申请内存和数据搬移,此时时间复杂度为 O ( n ) O(n) O(n),为最坏时间复杂度;
  • 均摊时间复杂度
    假设栈空间不够时,重新申请原来大小两倍的数组,每一步时间复杂度画图如下:
    入栈时间复杂度
    k次入栈操作,总共涉及k个数据的搬移,以及k次的简单入栈操作,平均下来,每个入栈操作只需要一个数据搬移和一次简单入栈操作,均摊时间复杂度为 O ( 1 ) O(1) 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. 栈在表达式求值中的应用

表达式求值使用两个栈完成,一个是保存操作数的栈,一个是保存运算符的栈。从左到右遍历表达式,将数字一次入栈,遇到运算符时,与栈顶比较:

  • 当前运算符比栈顶元素优先级高,则当前运算符入栈;
  • 当前运算符比栈顶元素优先级低或相同,则取出栈顶运算符,从操作数栈中取2个操作数,计算后将结果入操作数栈,再次比较;

表达式应用

3. 浏览器前进和后退功能应用

使用两个栈X,Y实现。首次浏览的页面一次压入X,点击后退按钮时从X取数据,一次压入Y;
当X栈中没有数据时,说明没有页面可以继续后退浏览了;当Y栈中没有数据时,说明没有页面可以继续前进浏览了。
1
2
在这里插入图片描述
当后退后查看新页面时,页面c无法通过前进、后退按钮重复查看,所以需要清空栈Y;即X中压入非Y栈中元素时,清空Y。
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值