栈是一种非常常见的数据结构-并且在程序中的应用非常的广泛
我们可以用数组来做一个对比
数组是一种线性结构,并且可以在数组的任意位置插入和删除数据
但是有时候我们为了实现某一种功能,必须对这种任意性加以限制
而队列和栈就是比较常见的受限制的线性结构
栈结构只能在一端(栈顶【另一端叫做栈底】)
添加(进栈)和删除(出栈)元素(新元素进栈的过程叫做进栈操作)
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