0
点赞
收藏
分享

微信扫一扫

线性结构,栈[堆栈](笔记)

穆熙沐 2022-01-07 阅读 27

1. 栈(堆栈)

  • 栈结构是什么,栈结构是一种受限制的线性结构
  • 栈的特征,先进后出、后进先出(LIFO – last in first out)
  • 栈只能在一端进行添加和删除,这一端被称为栈顶,另一端称为栈底。向栈顶添加数据称为进栈、入栈或压栈,删除数据又称为出栈或退栈

在这里插入图片描述

1.1 栈的封装

// 栈类
class Stack {
  constructor() {
    this.arr = []
  }

  // 1.push(Ele):添加一个新元素到栈顶位置
  push(Ele) {
    this.arr.push(Ele)
  }

  // 2.pop():移除栈顶的元素,同时返回被移除的元素
  pop() {
    return this.arr.pop()
  }

  // 3.peek():返回栈顶的元素,不对栈做任何修改
  peek() {
    return this.arr[this.arr.length - 1]
  }

  // 4.isEmpty():查看栈里有没有东西,没有就true,有就false
  isEmpty() {
    return this.arr.length == 0
  }

  // 5.size():返回栈里的元素个数
  size() {
    return this.arr.length
  }

  // 6.toString():将栈结构的内容以字符形式返回
  toString() {
    let resultStr = ""
    for (let i = 0; i < this.arr.length; i++) {
      resultStr += this.arr[i] + " "
    }
    return resultStr
  }
}

1.2 十进制转二进制

// 10 /  2  0
// 5  /  2  1
// 2  /  2  0
// 1  /  2  1
// 10 ---> 1010

// 封装十进制转二进制的方法
function DecChangeBin(decNum) {
  // 引用封装的栈类
  let stack = new Stack()
  // 当数不为零时一直循环
  while (decNum > 0) {
    // 余数为零或一时添加 
    stack.push(decNum % 2)
    // 向下取整,因为余数为一时已经获取到了那个一
    decNum = Math.floor(decNum / 2)
  }

  let resultStr = ''
  // 表示栈里还有东西
  while (!stack.isEmpty()) {
    // 按顺序弹栈
    resultStr += stack.pop()
  }
  return resultStr
}

let dec = 2048
let decChangeBin = DecChangeBin(dec)
console.log(`原十进制的数:${dec},现二进制的数:${decChangeBin}`);

1.3 智能重复

把数组中的字母重复对应前面数字的次数

在这里插入图片描述

// 把 2[1[a]3[b]2[3[c]4[b]]] 变成 abbbcccddddcccddddabbbcccddddcccdddd 这种形式
// 1. 当遇到数字连接[时 数字添加到栈1,栈2添加空字符串
// 2. 当遇到字母链接]时 把栈2最后一个空字符串变为这个字母
// 这里有必要说一下为什么要连接后面的括号,数字后面还有可能会是数字,字母同理
// 3. 当遇到]时(即使遇到相邻的也不会影响),栈1和栈2最后一位出栈
//    然后把栈2出栈的字母乘栈1数字的倍数,在拼接到栈2最后一个字母

// replace:两个参数(匹配到的字符,被替换成谁)
// match:能够找到所有匹配到的字符
// test:查询开头字符是否存在(可多个)
// substring:第一个参数截取第一个的多少位,返回剩余的

let str = '2[1[aaa]3[b]2[3[c]4[b]]]'
// 存放数字栈
let stackNum = []
// 存放字母栈
let stackStr = []
// 指针
let i = 0
// 存放剩余字符串
let rest = str
function smartRepeat(str) {
  while (i < str.length - 1) {
    rest = str.substring(i)
    // 当遇到数字连接[时 数字添加到栈1,栈2添加空字符串
    if (/^\d+\[/.test(rest)) {
      // match(/^(\d+)\[/)捕获 括号中的数放到数组中下标为1
      let num = Number(rest.match(/^(\d+)\[/)[1])
      stackNum.push(num)
      stackStr.push('')
      // 数字可能有多位 加一是[ 因为数字后面必为[
      i += num.toString().length + 1
      // 当遇到字母链接]时 把栈2最后一个空字符串变为这个字母
    } else if (/^\w+\]/.test(rest)) {
      let str = rest.match(/^(\w+)\]/)[1]
      stackStr[stackStr.length - 1] = str
      i += str.length
      // 当遇到]时(即使遇到相邻的也不会影响),栈1和栈2最后一位出栈
      // 然后把栈2出栈的字母乘栈1数字的倍数,在拼接到栈2最后一个字母
    } else if (/\]/.test(rest)) {
      let outNum = stackNum.pop()
      let outStr = stackStr.pop()
      // 'a'.repeat(3) 返回'aaa'
      stackStr[stackStr.length - 1] += outStr.repeat(outNum)
      i++
    }
  }
  // 因为在whil循环的时候专门少循环了一次 
  // 在数字栈中的第一项一定是最开始字符串第一项的数字
  // 而字母栈也是都乘好的就差第一个数字没有乘了
  return stackStr[0].repeat(stackNum[0])
}
smartRepeat(str)
举报

相关推荐

0 条评论