数据结构之Stack | 让我们一块来学习数据结构
栈的介绍
栈就是和列表类似的一种数据结构,它可用来解决计算机世界里的很多问题。栈是一种高 效的数据结构,因为数据只能在栈顶添加或删除,所以这样的操作很快,而且容易实现。 栈的使用遍布程序语言实现的方方面面,从表达式求值到处理函数调用
栈是一种特殊的列表,栈内的元素只能通过列表的一端访问,这一端称为栈顶。咖啡厅内 的一摞盘子是现实世界中常见的栈的例子。只能从最上面取盘子,盘子洗净后,也只能摞 在这一摞盘子的最上面。栈被称为一种后入先出(LIFO,last-in-first-out)的数据结构。
由于栈具有后入先出的特点,所以任何不在栈顶的元素都无法访问。为了得到栈底的元 素,必须先拿掉上面的元素。
对栈的两种主要操作是将一个元素压入栈和将一个元素弹出栈。入栈使用 push()
方法,出 栈使用 pop()
方法。图 一演示了入栈和出栈的过程。
另一个常用的操作是预览栈顶的元素。pop()
方法虽然可以访问栈顶的元素,但是调用该方 法后,栈顶元素也从栈中被永久性地删除了。peek()
方法则只返回栈顶元素,而不删除它。
栈的实现
实现一个栈,当务之急是决定存储数据的底层数据结构。这里采用的是数组。
我们的实现以定义 Stack 类开始:
class Stack {
constructor() {
this.dataStore = [];
this.top = 0;
}
push() { }
pop() { }
peek() { }
clear() { }
length() { }
empty() { }
toString(){ }
}
我们用数组 dataStore
保存栈内元素,构造函数将其初始化为一个空数组。变量 top
记录 栈顶位置,被构造函数初始化为 0,表示栈顶对应数组的起始位置 0。如果有元素被压入 栈,该变量的值将随之变化。
实现push方法
先来实现 push()
方法。当向栈中压入一个新元素时,需要将其保存在数组中变量 top
所对 应的位置,然后将 top
值加 1
,让其指向数组中下一个空位置。代码如下所示:
push(element) {
this.dataStore[++this.top] = element;
}
这里要特别注意 ++
操作符的位置,它放在 this.top
的后面,这样新入栈的元素就被放在 top
的当前值对应的位置,然后再将变量 top
的值加 1
,指向下一个位置。
实现pop方法
pop()
方法恰好与 push()
方法相反——它返回栈顶(被删除的)元素,同时将变量 top
的值减 1
:
pop() {
return this.dataStore[this.top--];
}
实现peek方法
peek()
方法返回数组的第 top-1
个位置的元素,即栈顶元素:
peek() {
return this.dataStore[this.top - 1];
}
如果对一个空栈调用 peek()
方法,结果为 undefined
。这是因为栈是空的,栈顶没有任何 元素。
实现length方法
有时候需要知道栈内存储了多少个元素。length()
方法通过返回变量 top
值的方式返回栈内的元素个数:
length() {
return this.top
}
实现clear方法
可以将变量 top
的值设为 0
,轻松清空一个栈:
clear() {
this.top = 0;
}
实现empty方法
empty()
方法可以知道一个Stack
是否是空的
empty() {
return this.top === 0;
}
使用Stack类解决问题
数制间的转化
可以利用栈将一个数字从一种数制转换成另一种数制。假设想将数字 n 转换为以 b 为基数 的数字,实现转换的算法如下。
- 最高位为
n % b
,将此位压入栈。 - 使用
n/b
代替n
。 - 重复步骤 1 和 2,直到 n 等于 0,且没有余数。
- 持续将栈内元素弹出,直到栈为空,依次将这些元素排列,就得到转换后数字的字符 串形式
此算法只针对基数为2~9的情况
代码实现
function mulBase(num, base=2) {
let tmp = new Stack();
while (num > 0) {
tmp.push(num % base)
num = Math.floor(num /= base);
}
let target = '';
while(tmp.length() > 0) {
target = target + tmp.pop();
}
return target;
}
console.log(mulBase(3,2)) // "11"
console.log(mulBase(3,6)) // "6"
回文字符串的判断
回文是指这样一种现象:一个单词、短语或数字,从前往后写和从后往前写都是一样的。 比如,单词“dad”、“racecar”就是回文;如果忽略空格和标点符号,下面这个句子也是回 文,“A man, a plan, a canal: Panama”;数字 1001 也是回文。
使用栈,可以轻松判断一个字符串是否是回文。我们将拿到的字符串的每个字符按从左至 右的顺序压入栈。当字符串中的字符都入栈后,栈内就保存了一个反转后的字符串,最后 的字符在栈顶,第一个字符在栈底。
function isPalindrome(word) {
if (typeof word !== "string") {
throw TypeError(`参数不是string类型`);
}
let tmp = new Stack();
for (let element of word) {
tmp.push(element)
}
let rword = '';
while (tmp.length() > 0) {
rword += tmp.pop()
}
console.log(rword);
return word === rword;
}
console.log(isPalindrome("racecar")) // true
console.log(isPalindrome("hello")) // false
参考资料
- 数据结构与算法JavaScript描述
数据结构之Stack | 让我们一块来学习数据结构的更多相关文章
- 数据结构之Queue | 让我们一块来学习数据结构
前面的两篇文章分别介绍了List和Stack,下面让我们一起来学习Queue 数据结构之List | 让我们一块来学习数据结构 数据结构之Stack | 让我们一块来学习数据结构 队列的概况 队列是一 ...
- 数据结构之LinkedList | 让我们一块来学习数据结构
highlight: monokai theme: vue-pro 上一篇文章中使用列表(List)对数据排序,当时底层储存数据的数据结构是数组.本文将讨论另外一种列表:链表.我们会解释为什么有时链表 ...
- 数据结构之Set | 让我们一块来学习数据结构
数组(列表).栈.队列和链表这些顺序数据结构对你来说应该不陌生了.现在我们要学习集合,这是一种不允许值重复的顺序数据结构.我们将要学到如何创建集合这种数据结构,如何添加和移除值,如何搜索值是否存在.你 ...
- 数据结构之List | 让我们一块来学习数据结构
列表[List]的定义 列表是一组有序的数据.每个列表中的数据项称为元素.在 JavaScript 中,列表中的元素 可以是任意数据类型.列表中可以保存多少元素并没有事先限定,实际使用时元素的数量 受 ...
- 《Java程序设计与数据结构教程(第二版)》学习指导
<Java程序设计与数据结构教程(第二版)>学习指导 欢迎关注"rocedu"微信公众号(手机上长按二维码) 做中教,做中学,实践中共同进步! 原文地址:http:// ...
- SqList *L 和 SqList * &L的区别/学习数据结构突然发现不太懂 小祥我查找总结了一下
小祥在学习李春葆的数据结构教程时发现一个小问题,建立顺序表和输出线性表,这两个函数的形参是不一样的. 代码在这里↓↓↓ //定义顺序表L的结构体 typedef struct { Elemtype d ...
- Java 数据结构之Stack
Stack类表示后进先出(LIFO)的对象堆栈.栈是一种非常常见的数据结构.Stack继承Vector,并对其进行了扩展. 用法: 1.只有一个构造函数: public Stack() {} 2.创建 ...
- 在Object-C中学习数据结构与算法之排序算法
笔者在学习数据结构与算法时,尝试着将排序算法以动画的形式呈现出来更加方便理解记忆,本文配合Demo 在Object-C中学习数据结构与算法之排序算法阅读更佳. 目录 选择排序 冒泡排序 插入排序 快速 ...
- Java 中的数据结构类 Stack
JDK 中的 Stack 类便是经典的数据结构栈的实现,它继承于线程安全的 Vector 类,而且它自身的线程不安全的方法上也加上了 synchronized 关键字,所以它的内部操作也是线程安全的哦 ...
随机推荐
- 那些容易犯错的c++保留字
本文首发 | 公众号:lunvey 目前正在学习vc++6.0开发,而这里面使用的是c++98标准. 保留字,也称关键字,是指在变量.函数.类中不得重新声明的名称. c++98中大致有48个保留字,这 ...
- Java Socket编程基础及深入讲解
原文链接:https://www.cnblogs.com/yiwangzhibujian/p/7107785.html 原文写的特别好,非常详细,但是禁止转载,那我就不再复制粘贴了! socket实现 ...
- 基于西门子S7-1500的大型焊接机全套程序,使用博图V14打开(带全部注释)
程序说明:本套程序是在从事自动化行业时候的做的项目的程序,经过在设备上运行测试,其中包含20多个轴的伺服控制以及模拟量,数字量IO的控制,包括扫描枪的读取,属于大型程序,总步数有好几万步. 本程序注释 ...
- 🤔 移动端 JS 引擎哪家强?美国硅谷找......
如果你喜欢我写的文章,可以把我的公众号设为星标 ,这样每次有更新就可以及时推送给你啦 在一般的移动端开发场景中,每次更新应用功能都是通过 Native 语言开发并通过应用市场版本分发来实现的.但是市场 ...
- 分布式流转开发常见报错FAQ
鸿蒙入门指南,小白速来!0基础学习路线分享,高效学习方法,重点答疑解惑--->[课程入口] HarmonyOS开发中分布式协同是非常重要的一个功能,大家在刚接触的时候可能会出现各种各样的错误.我 ...
- Win32API使用技巧 -- 置顶应用
Win32提供了SetForegroundWindow方法可以将应用设置到前台并激活,但是在某些场景下,只调用该接口会返回0,即设置失败.比如如下场景: 当前前台应用为一个全屏的应用,非前台应用的进程 ...
- android上实现0.5px线条
转: android上实现0.5px线条 由于安卓手机无法识别border: 0.5px,因此我们要用0.5px的话必须要借助css3中的-webkit-transform:scale缩放来实现. 原 ...
- 使用Spark加载数据到SQL Server列存储表
原文地址https://devblogs.microsoft.com/azure-sql/partitioning-on-spark-fast-loading-clustered-columnstor ...
- synchronized中锁是怎么升级的
在JDK1.6以前,使用synchronized就只有一种方式即重量级锁,而在JDK1.6以后,引入了偏向锁,轻量级锁,重量级锁,来减少竞争带来的上下文切换. 锁升级主要依赖对象头中的Mark Wor ...
- Python开发环境从零搭建-03-安装Python解释器并配置
想要从零开始搭建一个Python的开发环境说容易也容易 说难也能难倒一片开发人员,在接下来的一系列视频中,会详细的讲解如何一步步搭建python的开发环境 本文章是搭建环境的第3篇 讲解的内容是:安装 ...