JavaScript 讲述数据结构 - 栈结构

文章目录

  • 什么是栈结构 ?
    • 数组
    • 栈结构
      • 什么是函数调用栈?
  • 栈结构练习
  • 堆栈结构
  • 计算机基础知识补充 -- 基于栈理念理解十进制转二进制
  • 封装进制转换方法

什么是栈结构 ?

栈是一种非常常见的数据结构-并且在程序中的应用非常的广泛

我们可以用数组来做一个对比


数组

数组是一种线性结构,并且可以在数组的任意位置插入和删除数据

但是有时候我们为了实现某一种功能,必须对这种任意性加以限制

而队列和栈就是比较常见的受限制的线性结构


栈结构

栈结构只能在一端(栈顶【另一端叫做栈底】)

添加(进栈)和删除(出栈)元素(新元素进栈的过程叫做进栈操作)

LIFO(last in first out)后进先出(最后进栈的元素将会被第一个弹出栈空间)

什么是函数调用栈?

我们知道函数之间的相互调用:A 调用 B,B 调用 C,接着 C 又调用 D,这样的话,在执行过程中,先会将 A 压入栈,此时 A 是没有执行完毕的,所以不会弹出栈

在 A 执行过程中调用了 B,将 B 压入到栈,这个时候 B 在栈顶,A 在栈底

如果 B 执行完毕,那么 B 先弹出栈,A 再弹出栈,但是 B 没有执行完,B 又去调用了 C,C 没执行完又去调用了 D

那么栈顶到栈底现在为:A–>B–>C–>D–>
D 执行完先弹出栈,接着就是 C–>B–>A

我们经常会听到递归这个计算机名词,其实递归就是不断的自己调用自己,不会弹出栈,所以会有一个栈溢出的情况


栈结构练习

有六个元素 6、5、4、3、2、1 的顺序进栈,那么下面哪一个不是合法的出栈顺序

A. 5 4 3 6 1 2

B. 4 5 3 2 1 6

C. 3 4 6 5 2 1

D. 2 3 4 1 5 6

分析 A :

5 先出栈,那么必然 6 压栈了 --> 5 出去之后,4 进栈再出栈 --> 3 进栈再出栈 --> 然后 6 出栈 --> 接着就是 1 出栈,那么意味着 2 被压栈,所以 1 先出栈 2 再出栈,【正确】

分析 B :

4 先出栈,那么意味着 6,5 被压栈 --> 接着 5 出栈 --> 3 进栈,3 出栈 --> 2 进栈,2 出栈 --> 1 进栈,1 出栈 --> 6 出栈 【正确】

分析 C :

3 先出栈,那么意味着 6,5,4 被压栈 --> 然后 4 出栈 --> 接着 6 出栈,但是现在 6 被压栈,进栈时后进栈的 5 还没有出去,所以这就造成了错误 【错误】

分析 D :

2 先出栈,那么意味着 6,5,4,3 都被压栈 – 3 出栈 --> 4 出栈 --> 然后 1 进栈,1 出栈 --> 5 出栈 --> 6 出栈 【正确】


堆栈结构

'use strict'

// 封装栈类
function Stack() {
  // 栈中的属性
  this.items = []

  // 栈的常见操作
  // push(element):添加一个新元素到栈顶位置
  Stack.prototype.push = function (element) {
    this.items.push(element)
  }
  // pop():移除栈顶元素,同时返回被移除元素
  Stack.prototype.pop = function () {
    return this.items.pop()
  }
  // peek():返回栈顶元素,不对栈做任何修改
  Stack.prototype.peek = function () {
    return this.items[this.items.length - 1]
  }
  // isEmpty():如果栈里面没有任何元素就返回true
  Stack.prototype.isEmpty = function () {
    return this.items.length === 0
  }
  // size():返回栈里的元素个数
  Stack.prototype.size = function () {
    return this.items.length
  }
  // toString():将栈结构的内容以字符串的形式返回
  Stack.prototype.toString = function () {
    let resultString = ''
    for (let i = 0; i < this.items.length; i++) {
      resultString += this.items[i] + ' '
    }
    return resultString
  }
}

// 栈的使用
let s = new Stack()

// 验证
s.push(10)
s.push(9)
s.push(8)
s.push(7)
s.push(6)
s.push(5)
console.log(s.items)
// [ 10, 9, 8, 7, 6, 5 ]

s.pop()
s.pop()
console.log(s.items)
// [ 10, 9, 8, 7 ]

console.log(s.peek())
// 7

console.log(s.isEmpty())
// false

console.log(s.size())
// 4


计算机基础知识补充 – 基于栈理念理解十进制转二进制

在计算机中,二进制非常的重要,因为计算机里面所有的内容都是用二进制数字表示的

把十进制转换为二进制,我们可以将该十进制数字与 2 整除(二进制满二进一),知道结果为 0 为止

然后翻转取出余数,就是一个二进制数了

就像这样:

十进制数:100

100 / 2 = 50 …0

50 / 2 = 25 … 0

25 / 2 = 12 … 1

12 / 2 = 6 … 0

6 / 2 = 3 … 0

3 / 2 = 1 … 1

1 / 2 = 0 … 1

二进制:1100100

这就与栈有些类似了,依次得出元素,接着将最后存储的数字第一个拿出来进行排序,形成一个进栈出栈的原理


封装进制转换方法

function DecToBin(decNumber) {
  let stack = new Stack()
  while (decNumber > 0) {
    stack.push(decNumber % 2)
    decNumber = Math.floor(decNumber / 2)
  }
  let binString = ''
  while (!stack.isEmpty()) {
    binString += stack.pop()
  }
  return binString
}

console.log(DecToBin(100))
console.log(DecToBin(128))
console.log(DecToBin(800))
console.log(DecToBin(10))

// 1100100
// 10000000
// 1100100000
// 1010

你可能感兴趣的:(数据结构,javascript,数据结构,前端,计算机,栈结构)