数据结构与算法JS描述之栈和队列

数据结构与算法JS描述之栈和队列

博主wx: -GuanEr-,加博主进前端交流群

参考资料

数据结构与算法JS描述,[美] Michael McMillan 著,王群锋 杜欢 译

写在前面

写该系列的博客,初衷是帮助自己和初学者,奠定更高层次的编程基础和理念,能让大家对 JS 有更深层次的认知,并且借助 JS 了解高级的编程思想。

所有对于某个数据结构的算法的示范,并不是标准答案,只是我根据经验模仿了各种资料和其他成熟语言中的写法,如果有写的不精致的地方,或者更好的写法,联系我,我加以改正。

本来想用构造函数的形式实现这些数据结构,但是既然技术在更新,用新的语法可能更好一点。所以所有的代码实现方式都是 ES6+ 的代码。

一、什么是栈,什么是队列

1. 栈
  • 栈是数据临时存储的地方,是一个动态内存区域
  • 栈是只能在一端进行插入和删除操作的特殊线性表
  • 栈按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶
  • 栈具有记忆作用,对栈的插入与删除操作中,不需要改变栈底指针
  • 需要读数据的时候从栈顶开始弹出数据,最后一个数据被第一个读出来
  • 所以栈被称为一种后入先出的数据结构(LIFO,Last-In-First-Out)
  • 允许进行插入和删除操作的一端称为栈顶(top),另一端为栈底(bottom)
  • 栈底固定,而栈顶浮动
  • 插入一般称为进栈(PUSH),删除则称为退栈(POP)
  • 栈中元素个数为零时称为空栈

在前端开发的过程中,我们很少遇见一批数据需要用栈这种数据结构来管理,所以对于栈的概念比较淡薄,其实有一个非常形象的栈的例子,就是递归。还有函数的调用、执行都在栈里,闭包也跟栈有关系。

栈在程序的运行中有着举足轻重的作用。最重要的是栈保存了一个函数调用时所需要的维护信息,这常常称之为堆栈帧或者活动记录。堆栈帧一般包含两个重要的信息,函数的返回地址和参数和临时变量:包括函数的非静态局部变量以及编译器自动生成的其他临时变量。

这里我找到了一个非常具体的介绍 JS 函数执行栈的例子,感谢作者的分享,真心建议大家一看,作者写的特别好。

栈的概述图

在这里插入图片描述

2. 队列
  • 队列和栈一样,都是一种受限制的线性数据结构
  • 队列只允许在列表的前端进行删除操作,在表的后端进行插入操作
  • 进行插入操作的一端成为队尾,进行删除操作的一端成为队头
  • 在队列中插入一个队列元素成为入队,删除一个元素称为出队
  • 最早入队的元素最早出队,所以队列被称为先进先出表(FIFO,First-In-First-Out)
  • 队列中没有元素时,成为空队列

相对于栈,对于队列这种数据结构,我们可能要较为熟悉一点,但也并不常用,这里举一个队列相关的列子,就是传统的贪吃蛇游戏,写过这个游戏的人应该都知道,蛇在背景上移动的基础逻辑是,头部添加新的元素,尾部删除旧的元素。

队列的概述图

在这里插入图片描述

其实概念搞清楚了之后,代码实现很简单的。但是由于 JS 语言本身的特点,我们写的代码如果完全按照我们的规定去执行,那就能体现出这种概念性,但是如果随意操作,那这个概念性就没那么强烈了,就像类,抽象类,类的 gettersetter 一样。

二、用 JS 实现栈及其基础算法

1. 栈需要实现的基本算法
  • top 属性,保留栈顶的位置,要在栈内做操作时,通过 top 找到栈顶的位置,做操作
  • push 方法,从栈顶向栈内添加新元素(入栈)
  • pop 方法,从栈顶删除元素(出栈)
  • peek 方法,读取栈顶的元素,其实可以在 pop 的同时拿到栈顶的元素,但是一定会删除,有时候不需要删除,只想读取栈顶的元素
  • clear 方法,清空栈
2. 代码
class Stack {
  top = 0; // 栈顶的位置
  data = []; // 数据源

  push(el) {
    this.data[this.top] = el;
    this.top++;

    // 简写: this.data[this.top++] = el;
  }

  pop() {
    const lastEl = this.data[this.top - 1];
    this.data[--this.top] = null;
    return lastEl;
  }

  peek() {
    return this.data[this.top - 1];
  }

  clear() {
    this.data = [];
    this.top = 0;
  }
}

三、用 JS 实现队列及其基础算法

1. 队列需要实现的基本算法
  • front 属性,队头的位置
  • end 属性,队尾的位置
  • first 方法,读取队首的元素
  • last 方法,读取队尾的元素
  • shift 方法,从队首删除一个元素
  • push 方法,向队尾添加一个元素
2. 代码
class Queue {
  front = 0; // 队头的位置
  end = 1; // 队尾的位置
  data = [45, 67, 89, 90]; // 数据源

  push(el) {
    this.data[this.end++] = el;
  }

  shift() {
    const firstEl = this.data[this.front];
    this.data[this.front++] = null;
    return firstEl;
  }

  first() {
    return this.data[this.front];
  }

  last() {
    return this.data[this.end - 1];
  }

  clear() {
    this.data = [];
    this.front = 0;
    this.end = 1;
  }
}

代码太简单了,所以我就没有写注释,但是重要的是我们要借助这些代码理解栈和队列这种数据结构。

扫码拉你进入前端技术交流群

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锋利的二丫

如果对您有帮助,请博主喝杯奶茶

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值