当前位置: 首页 > article >正文

javascript实现Stack(栈)数据结构

上一篇文章我们理解了List这种数据结构,知道了它的特点和一些使用场景,这篇文章我们就来看一下栈这种数据结构,这里的栈可不是客栈哦,哈哈

栈其实和List非常像,使用javascript实现都是基于数组来实现

尝试理解Stack

1.栈只能在栈顶进行入栈和出栈( 我们可以尝试把栈想象成一个瓶子,瓶子只有一个瓶口,所有的东西都只能从瓶口塞进去,丛瓶口拿出来)
2. 栈是一种后进先出的数据结构(LIFO,last-in-first-out)(最后塞进瓶子的东西一定最先从瓶子里面拿出来)
3. 栈也有自己的属性和方法(瓶子里面可以塞很多东西,我们也可以取出瓶子里的东西,或清空整个瓶子)

代码实现

function Stack () {
  // 当前栈的数据
  this.data = [];
  // 栈顶位置
  this.top = 0
  // 向栈中压入一个元素
  this.push = function (elem) {
    this.data[this.top++] = elem
  }
  // 从栈中弹出(删除)栈顶元素并返回
  this.pop = function() {
    return this.data[--this.top]
  }
  // 仅返回栈顶元素,不删除
  this.peek = function() {
    return this.data[this.top-1]
  }
  // 返回栈中的元素个数
  this.length = function() {
    return this.top
  }
  // 清空栈
  this.clear = function() {
    this.top = 0
  }
}

测试一下

const s = new Stack();
s.push("David");
s.push("Raymond");
s.push("Bryan");
console.log('当前栈长度length:', s.length());
console.log('当前栈顶元素为:', s.peek());

const popped = s.pop()
console.log('被弹出的栈顶元素为:', popped);
console.log('当前栈顶元素为:', s.peek());
s.push("Cynthia");
console.log('当前栈顶元素为:', s.peek());
s.clear()
console.log('执行了清空栈');
console.log('当前栈长度length:', s.length());
console.log('当前栈顶元素为:', s.peek());
s.push("Clayton");
console.log('当前栈顶元素为:', s.peek());

测试结果:
在这里插入图片描述

实际应用

  1. 进制转换
/**
 * 进制转换
 * @param num 
 * @param base 
 */
function mulBase(num, base) {
  const s = new Stack()
  do {
    s.push(num%base)
    num = Math.floor(num/base)
  } while (num > 0)

  let converted = ''
  while(s.length() > 0) {
    converted += s.pop()
  }
  return converted
}
console.log('将10转换为二进制:', mulBase(10, 2))
console.log('将32转换为二进制:', mulBase(32, 2))
console.log('将125转换为八进制:', mulBase(125, 8))

在这里插入图片描述
2. 判断回文字符串

/**
 * 判断一个字符串是否回文字符串
 * @param word 需要判断的字符串
 */
function isPalindrome(word) {
  const s = new Stack()
  for(let i = 0; i < word.length; i ++) {
    s.push(word[i])
  }

  let rword = ''
  while(s.length() > 0) {
    rword += s.pop()
  }
  if(word === rword) return true
  return false
}
const word = "hello";
if (isPalindrome(word)) {
  console.log(word + " 是回文字符串");
}
else {
  console.log(word + " 不是回文字符串");
}

const word1 = "racecar"
if (isPalindrome(word1)) {
  console.log(word1 + " 是回文字符串");
}
else {
  console.log(word1 + " 不是回文字符串");
}

在这里插入图片描述
3. 模拟递归过程,阶乘函数

/**
 * 使用栈模拟递归过程,返回n的阶乘 n!
 * @param n 
 * @returns 
 */
function fact(n) {
  const s = new Stack()
  while (n > 1) {
    s.push(n--)
  }

  let product = 1
  while(s.length() > 0) {
    product *= s.pop()
  }
  return product
}
console.log('5的阶乘为:', fact(5))
  1. 表达式括号匹配问题
/**
 * 计算某个表达式中的括号是否匹配
 * @param str 表达式
 * @returns 匹配情况
 */
function isMatch (str) {
  const match = {
    match: true,
    position: -1
  }
  const left = new Stack()
  const right = new Stack()
  const ml = ['(', '[', '{']
  const mr = [ ')', ']', '}']
  for (let i = 0; i < str.length; i ++) {
    if (ml.includes(str[i])) {
      left.push({
        value: str[i],
        position: i
      })
    }
    if (mr.includes(str[i])) {
      right.push({
        value: str[i],
        position: i
      })
    }
  }

  while (left.length() || right.length()) {
    const l = left.pop()
    const r = right.pop()
    let index
    if (l) index = ml.findIndex((item) => item === l.value)
    else index = mr.findIndex((item) => item === r.value)
    if (mr[index] !== r?.value || ml[index] !== l?.value) {
      match.match = false
      match.position = l ? l.position : r.positon
      return match
    }
  }

  return match
}

const string = '2.3 + 23/12 + (3.14159 * 0.24'
if (!isMatch(string).match) {
  console.log(`表达式${string}括号不匹配,不匹配位置为:`, isMatch(string).position)
} else {
  console.log(`表达式${string}括号匹配成功`)
}
const string1 = '({ab}(c)ccc['
if (!isMatch(string1).match) {
  console.log(`表达式${string1}括号不匹配,不匹配位置为:`, isMatch(string1).position)
} else {
  console.log(`表达式${string1}括号匹配成功`)
}

在这里插入图片描述
好了,文章就到这里了,大家如果想了解更多就去看《数据结构与算法javascript描述》这本书吧,希望大家都能有所收获~


http://www.kler.cn/news/163340.html

相关文章:

  • PySpark开发环境搭建常见问题及解决
  • 网站内容审核功能的重要性
  • MYSQL练题笔记-子查询-换座位
  • unity 2d 入门 飞翔小鸟 小鸟碰撞 及死亡(九)
  • EOCR-CT电流互感器与SR-CT区别简介
  • 『Linux升级路』进度条小程序
  • vue使用甘特图dhtmlxgantt + gantt.addTaskLayer
  • 基于高通MSM8953平台android9.0的GPIO驱动开发
  • Hbase JAVA API 增删改查操作
  • 【电子取证篇】汽车取证数据提取与汽车取证实例浅析(附标准下载)
  • imazing正在查找最新的apple mobile device组件
  • SpringBoot AOP切面实现对自定义注解的属性动态修改
  • 无重复字符的最长子串(LeetCode 3)
  • 记录一下Mac配置SpringBoot开发环境
  • “华为杯”研究生数学建模竞赛2016年-【华为杯】A题:无人机在抢险救灾中的优化运用(附获奖论文及MATLAB代码实现)
  • perf与火焰图-性能分析工具
  • IntelliJ IDEA使用Eval Reset
  • Unity使用打成图集的Sprite作为模型贴图使用的问题
  • ubuntu server 20.04 备份和恢复 系统 LTS
  • 小红书用户采集工具:掌握策略,轻松吸引潜在客户
  • 【flink番外篇】1、flink的23种常用算子介绍及详细示例(1)- map、flatmap和filter
  • 【链表Linked List】力扣-82 删除链表中的重复元素II
  • velocity-engine-core是什么?Velocity模板引擎的使用
  • pr抖音素材42个手机竖屏抖音视频转场特效PR剪辑模板
  • 浅谈5G基站节能及数字化管理解决方案的设计与应用-安科瑞 蒋静
  • 智慧城市是什么?为什么要建智慧城市?
  • 8_企业架构缓存中间件分布式memcached
  • 云原生系列1
  • 力扣(LeetCode)1038. 从二叉搜索树到更大和树(C++)
  • 卷积之后通道数为什么变了