Javascript常见数据结构——栈

本文详细介绍了JavaScript中的栈数据结构,包括创建、入栈、出栈、查看栈顶元素、清空栈及获取栈中元素数量等操作。通过自定义栈类进行了两次改进,确保了数据的安全性。此外,还展示了栈在实现十进制转二进制、多进制转换、回文字符串判断及括号匹配等实际问题中的应用。栈作为一种重要的数据结构,其后进先出的特性在编程中有着广泛的应用。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Javascript常见数据结构——栈

一、概述

数据结构是指 相互之间存在一种或多种特定关系的数据组成的集合

二、栈

1.创建数据结构

是一种遵循 后进先出 原则的有序数据集

栈顶 栈底 入栈 出栈

栈结构也被用在编译器和内存中保存变量

功能需求:

入栈也叫压栈 栈顶添加数据 push
出栈也叫弹栈 栈顶删除并返回数据 pop
返回栈顶数据 peek
清空栈 clear 
返回栈中数据个数

自定义栈

class Stack{
        constructor() {
            this.items =[]
        }
        // 入栈 压栈
        push(data){
            this.items.push(data)
        }
        // 出栈 弹栈
        pop(){
            if(!this.size()){
                console.warn('当前栈为空,默认返回undefined')
            }
            return this.items.pop()
        }
        // 返回栈顶数据
        peek(){
            if(!this.size()){
                console.warn('当前栈为空,默认返回undefined')
            }
            return this.items[this.items.length-1]
        }
        // 清空栈
        clear(){
            this.items = []
        }
        //返回栈中数据个数
        size(){
            return this.items.length
        }
    }
当前栈还是存在一些问题 外界是可以轻松拿到 items 的值的可以直接通过数组的api 进行修改 所以在这里 需要进行改进一下
// 改进 1
let Stack = (function (){
    let items = []
    return  class {
        // 入栈 压栈
        push(data) {
            items.push(data)
        }

        // 出栈
        pop() {
            if (!this.size()) {
                console.warn('当前栈为空,默认返回undefined')
            }
            return items.pop()
        }

        // 返回栈顶数据
        peek() {
            if (!this.size()) {
                console.warn('当前栈为空,默认返回undefined')
            }
            return items[items.length - 1]
        }

        // 清空栈
        clear() {
            items = []
        }

        //返回栈中数据个数
        size() {
            return items.length
        }
    }
})()
通过当前栈中创建出来的所有实例对象 他们的值都能相互访问到 并不是我们所期望的这个时候 我们可以采用 Symbol 作为变量名 Symbol是独一无的虽然 外界可以看到 里边的值 但是外界直接访问是访问不到的
// 改进 2
let Stack = (function (){
  let symbol = Symbol()
  return  class {
    constructor() {
      this[symbol] = []
    }
    // 入栈 压栈 
    push(...rest) {
      // 利用Es6 新增的剩余参数 可以优化入栈 一次性可以push多个
      this[symbol].push(rest)
    }

    // 出栈
    pop() {
      if (!this.size()) {
        console.warn('当前栈为空,默认返回undefined')
      }
      return this[symbol].pop()
    }

    // 返回栈顶数据
    peek() {
      if (!this.size()) {
        console.warn('当前栈为空,默认返回undefined')
      }
      return this[symbol][this[symbol].length - 1]
    }

    // 清空栈
    clear() {
      this[symbol] = []
    }

    //返回栈中数据个数
    size() {
      return this[symbol].length
    }
  }
})()

2.使用栈来实现十进制转二进制

// 十进制二进制转换
    function baseConverter2(number){
        let stack = new Stack()
        let result = ''

        // 余数入栈
        while(number){
            // 取余数
            stack.push(number%2)
            // 取商 取整运算
            number = number/2|0
        }
        // 余数出栈
        while (stack.size()){
            result += stack.pop()
        }
        return result
    }

3.使用栈来实现十进制转多进制

这里我们采用了闭包
特点 : 
1.两个函数 内部函数 使用了外部函数的参数和变量 导致参数不会被回收 使其一直保存在内存中
2.并且外部无法访问到闭包内的内容 不会污染全局变量
3.闭包内可以访问函数内部的变量
缺点 : 
由于闭包会使得函数中的变量都被保存在内存中,内存消耗很大,所以不能滥用闭包,否则会造成网页性能问题 在ie中 会导致 内存泄漏 解决方法是 再退出函数之前 将不使用的局部变量删除
// 十进制 多进制转换
let baseConverter = (function(){
    let sign = '';
    for (let i=0;i<10;i++)sign+=i;
    for (let i=97;i<123;i++){
        sign+=String.fromCharCode(i)
    }
    // 第一个参数表示 需要转换的十进制数 第二个参数表示 需要转换的进制数
    return function (number,base=2){
        let stack = new Stack()
        let result =''
        // 特殊情况 0 的转换
        if(number===0)return "0"
        // 余数 入栈 压栈
        while(number){
            // 取余数 字符串是可以通过下标进行取值的
            stack.push(sign[number%base])
            // 取值 位运算符 x|0  如果是整数 返回本身 如果是小数 那那么会舍去小数
            number =number/base|0
        }
        // 余数 出栈 弹栈
        while(stack.size()){
            result +=stack.pop()
        }
        return result
    }
})()

4.使用栈来实现判断是否为回文字符串

判断是否是回文字符串
思路 将字符串倒过来 与 原字符串 进行对比
上海自来水来自海上
蜜蜂采蜂蜜 我爱你你爱我
// 通过栈判断是否为回文字符串
function isPalindrome(str){
    let stack = new Stack();
    let pStr = "";
    // 按照顺序入栈
    // 此时的...rest 不是一组数据 它是一种结构
    // 类似于 "1" "2" "3" "4"
    stack.push(...str)
    // 按照顺序出栈
    while(stack.size()){
        pStr +=stack.pop()
    }
    return pStr === str
}

5.判断字符串括号是否匹配

// 判断符号是否闭合
// 思路 最先出现的右括号 一定与最后出现的左括号匹配
function isSignMatch(str) {
    // 定义基础符号
    let startSign = ['{', '[', '('],
        endSign = ['}', ']', ')']
    // 定义栈
    let stack = new Stack()

    // 逐字检查
    for (let i = 0; i < str.length; i++) {
        let s = str[i]
        // 左括号 入栈操作
        if (startSign.includes(s)) {
            stack.push(s)
        }
        // 右括号 
        if (endSign.includes(s)) {
            // 最后出现的左括号(左括号执行出栈操作)要和 最先出现的右括号匹配
            if (startSign.indexOf(stack.pop()) !== endSign.indexOf(s)) {
                    return false
            }
        }
    }
    // 最后判断 左括号是否出栈完毕
    return stack.size()===0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

貂蝉的腿毛

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值