JS数据结构0x002:栈

虚烬
• 阅读 1334

0x000 概述

今天玩得是栈,栈的用处非常广泛啊,比如函数的调用栈啊,h5historystateapi啊,之类的,一坨一坨的。

0x001 什么是栈

栈就是一个后入先出的数组,并且这个数组只能从一端进来,再从这一端出去,就像是放在长筒纸盒里面的羽毛球,他只有两个动作

  • push: 将数据推入栈中
  • pop:将数据弹出栈

JS数据结构0x002:栈

0x002 初始化

依旧使用数组来模拟栈

function init() {
    return []
}

0x003 推入

function push(stack, data) {
    stack.push(data)
}

0x004 弹出

function pop(stack) {
    return stack.pop()
}

0x005 使用

function main() {
    let stack = init() // stack: []
    stack = push(stack, 1) // stack: [1]
    stack = push(stack, 2) // stack: [1, 2]
    stack = push(stack, 3) // stack: [1, 2, 3]
    pop(stack) // 3 stack:[1, 2]
    pop(stack) // 2 stack:[1]
    pop(stack) // 1 stack:[]
}

main()

0x006 注意

平常我们依旧不会这么使用,而是

let stack=[] // []
stack.push(1) // [1]
stack.push(2) // [1, 2]
stack.push(3) // [1, 2, 3]
stack.pop() // 3
stack.pop() // 2 
stack.pop() // 1

0x007 栗子:10以内的波兰计算器

这是一个中缀转后缀并计算表达式结果的栗子,为了简单只实现10以内任意数量的加法和减法,完整的波兰计算器可以看另一个我的完整实现
  • 效果

JS数据结构0x002:栈

  • 页面其实可有可无,这里还是实现了一下

    <div class="container">
        <input type="text" class="form-control" id="inputText">
        <button class="btn btn-primary mt-1" id="btnCalculate">计算</button>
        <hr>
        <p id="pResult">
    
        </p>
    </div>
    <script src="index.js"></script>
    <script>
        let $btnCalculate = document.getElementById('btnCalculate')
        let $inputText = document.getElementById('inputText')
        let $pResult = document.getElementById('pResult')
        $btnCalculate.onclick = () => {
            $pResult.textContent=calculate($inputText.value)
        }
    </script>
  • 核心的calculate函数

    function calculate(input) {
        let tokenStack = input.split('').reverse() 
        let rpnStack = []
        let operationStack = []
    
        // 第一个循环 
        while (tokenStack.length) {  
            let t = tokenStack.pop()
            if (t.match(/[0-9]/)) {
                rpnStack.push(t)
                continue
            }
            if (t.match(/[\+\-]/)) {
                while (operationStack.length) {
                    rpnStack.push(operationStack.pop())
                }
                operationStack.push(t)
                continue
            }
    
            throw `error: unknow charactor: ${t}`
        }
        while (operationStack.length) {
            rpnStack.push(operationStack.pop())
        }
        rpnStack = rpnStack.reverse()
        
        
        let resultStack = []
        while (rpnStack.length) {
            let t = rpnStack.pop()+''
            if (t.match(/[0-9]/)) {
                resultStack.push(+t)
                continue
            }
            if (t === '+') {
                let num1 = resultStack.pop()
                let num2 = resultStack.pop()
                rpnStack.push(num2 + num1)
                continue
            }
            if (t === '-') {
                let num1 = resultStack.pop()
                let num2 = resultStack.pop()
                rpnStack.push(num2 - num1)
                continue
            }
        }
    
    
        return resultStack[0]
    }
  • 说明
    这个函数中用了4个栈

    • tokenStack:用来存放词素
    • operationStack:在中缀转后缀的过程中临时存放操作符
    • rpnStack:存放后缀表达式
    • resultStack:存放计算过程中的数字
  • 过程说明

    • 将表达式分割成数组,但是不是我们要的顺序,所以reverse一下:1+2-3+4-5->['5','-','4','+','3','-','2','+,'1']
    • 上面分割之后是中缀表达式,这里要转化为后缀表达式:['5','-','4','+','3','-','2','+,'1']->['1','2','+','3','-','4','+','5','-']
    • 将后缀表达式元素取出,如果是数组,就推入resultStack,如果是+、-,就从resultStack中取出数按符号做操作,将结果再推入resultStack,直到rpnStack为空:['1','2','+','3','-','4','+','5','-']->-1`

0x008 资源

点赞
收藏
评论区
推荐文章
待兔 待兔
1年前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Easter79 Easter79
3年前
stack顺序存储结构
《偶刚开始学习数据结构,欢迎拍砖111》栈是只能通过访问它的一段来实现数据存储的一种线性数据结构,换句话来说就是先进后出的原则,FILO,与队列刚好相反哈,现在只说stack。栈包括以下几种基本运算(1)初始化(2)判断是否为空(3)push(4)pop(5)top其他的则根据这几种基本操作进行组合,即可实现。栈的实现同样
Irene181 Irene181
4年前
一篇文章带你了解Python递归函数
一、什么是递归函数?在函数内部,可以调用其他函数。如果一个函数在内部调用自身本身,这个函数就是递归函数。二、函数的递归调用原理实际上递归函数是在栈内存上递归执行的,每次递归执行一次就会耗费一些栈内存。栈内存的大小是限制递归深度的重要因素三、案例分析1.求阶乘计算阶乘n!1x2x3x…xn,可以用
菜园前端 菜园前端
2年前
什么是JavaScript 调用栈?
原文链接:什么是调用栈?我们写的JS代码大多数都是同步模式,也就是从上往下依次执行。后一个任务必须要等前一个任务结束才能开始执行,程序的执行顺序和我们代码的编写顺序是完全一致的。程序执行中每遇到一个任务都会先入栈,当前入栈的任务执行完毕后就会出栈。本来栈的
九路 九路
4年前
5 手写Java Stack 核心源码
Stack是Java中常用的数据结构之一,Stack具有"后进先出(LIFO)"的性质。只能在一端进行插入或者删除,即压栈与出栈栈的实现比较简单,性质也简单。可以用一个数组来实现栈结构。1.入栈的时候,只在数组尾部插入2.出栈的时候,只在数组尾部删除我们来看一下Stack的用法:如下publicstaticvoidmai
Wesley13 Wesley13
3年前
C语言利用va_list、va_start、va_end、va_arg宏定义可变参数的函数
在定义可变参数的函数之前,先来理解一下函数参数的传递原理:1、函数参数是以栈这种数据结构来存取的,在函数参数列表中,从右至左依次入栈。2、参数的内存存放格式:参数的内存地址存放在内存的堆栈段中,在执行函数的时候,从最后一个(最右边)参数开始入栈。因此栈底高地址,栈顶低地址,举个例子说明一下:voidtest(inta,floatb,ch
Stella981 Stella981
3年前
JVM 字节码指令表
字节码助记符指令含义0x00nop什么都不做0x01aconst\_null将null推送至栈顶0x02iconst\_m1将int型1推送至栈顶0x03iconst\_0将int型0推送至栈顶0x04iconst\_1将int型1推送至栈顶0x05ic
Wesley13 Wesley13
3年前
Java学习系列——第3课Java 高级教程
java数据结构  1)【概述】  Java的工具包提供了强大的数据结构在的Java中的数据结构主要包括以下几种接口和类:枚举(枚举)位集合(位集合)向量(矢量)栈(栈)字典(词典)哈希表(哈希表)属性(属性)
Wesley13 Wesley13
3年前
Java内存管理
一、Java内存分类1、Java有几种存储区域?\寄存器\在CPU内部,开发人员不能通过代码来控制寄存器的分配,由编译器来管理\栈\在Windows下,栈是向低地址扩展的数据结构,是一块连续的内存的区域,即栈顶的地址和栈的最大容量是系统预先规定好的。\优点:由系统自动分配,速度较快。
菜园前端 菜园前端
2年前
什么是栈?
原文链接:栈是基础数据结构,栈是一种遵循后进先出原则的有序集合,添加新元素的一端称为栈顶,另一端称为栈底。操作栈的元素时,只能从栈顶操作(添加、移除、取值)。实现功能在JavaScript中没有栈,但是可以通过Array实现栈的所有功能push()入栈po
深度学习 深度学习
1个月前
链表栈实现指南:从基础到实践
一、简介和特点链表栈是一种使用链表实现的栈数据结构,遵循后进先出(LIFO)原则。本文实现的链表栈通过动态内存分配节点,避免了数组实现的固定大小限制。‌主要特点‌:1.动态大小:无需预先分配固定空间2.高效操作:入栈和出栈都是O(1)时间复杂度3.内存效率