什么是栈?
我觉得理解数据结构的时候在脑海中必须要有一种模型,比如当提到栈的时候,我们就要想起手枪弹夹,联想一下子弹是不是先进后出,后进先出的。
还有生活中的放
托盘最后放上的托盘,最先放置的使用的时候往往最后被取出使用,有了以上的这种概念之后我们在进行下一步的总结。
栈(stack)是一种受限的线性表:
LIFO( last in first out)表示后进入的元素,第一个弹出栈空间。- 限制只允许在线性表的一端进行插入或删除操作。这一端被称为
栈顶,相对的,把另一端称为栈底。 - 向一个栈插入新元素又称为
进栈、入栈、或压栈,这个操作是把新元素放到栈顶元素的上面,使之称为新的栈顶元素。 - 从一个栈中删除元素又称为
出栈或退栈,它是把栈顶元素删除掉,使其相邻元素称为新的栈顶元素。
下面有图的形式来表示一下栈的结构
栈的特点:先进后出,后进先出
程序中的栈结构
- 函数调用栈:A(B(C(D()))): 即 A 函数中调用 B,B 调用 C,C 调用 D;在 A 执行的过程中会将 A 压入栈,随后 B 执行时 B 也被压入栈,函数 C 和 D 执行时也会被压入栈。所以当前栈的顺序为:A->B->C->D(栈顶);函数 D 执行完之后,会弹出栈被释放,弹出栈的顺序为 D->C->B->A;
- 递归: 为什么没有停止条件的递归会造成栈溢出?比如函数 A 为递归函数,不断地调用自己(因为函数还没有执行完,不会把函数弹出栈),不停地把相同的函数 A 压入栈,最后造成栈溢出(Queue Overfloat)。
练习
题目:有 6 个元素 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
题目解释。题目所说的按顺序进栈指的不是一次性全部进栈,而是有进有出,进栈顺序为 6 -> 5 -> 4 -> 3 -> 2 -> 1。
A
5 4 3 1
6 -> 6 -> 6 -> 6 -> 6 -> 6 -> 2 -> 2
B
4
5 5 3 2 1
6 -> 6 -> 6 -> 6 -> 6 -> 6 -> 6 -> 6
C
3
4 4
5 5 5 ? 5还没出栈6怎么能出栈呢????
6 -> 6 -> 6
D
2
3 3
4 4 4 1
5 5 5 5 5 5
6 -> 6 -> 6 -> 6 -> 6 -> 6 -> 6
栈结构实现
栈常见的操作
push()添加一个新元素到栈顶位置。pop()移除栈顶的元素,同时返回被移除的元素。peek()返回栈顶的元素,不对栈做任何修改(该方法不会移除栈顶的元素,仅仅返回它)。isEmpty()如果栈里没有任何元素就返回true,否则返回false。size()返回栈里的元素个数。这个方法和数组的length属性类似。print()将栈结构的内容以字符串的形式返回。
JavaScript 代码实现栈结构
//采用Es5 的写法来写。
//栈可以抽象成给手枪弹夹装子弹。
function Stack() {
//用来存储数据
this.items = []
}
//定义栈的基本操作
//1. 把元素压入栈中
Stack.prototype.push = function (element) {
this.items.push(element)
}
//2. 从栈中取出元素
Stack.prototype.pop = function () {
return this.items.pop()
}
//3. 查看一下栈顶元素
Stack.prototype.peek = function () {
return this.items[this.items.length - 1]
}
//4. 判断栈是否为空
Stack.prototype.isEmpty = function () {
return this.items.length === 0
}
//5. 获取栈中的元素个数
Stack.prototype.size = function () {
return this.items.length
}
//6. 查看当前栈里面的内容
Stack.prototype.print = function () {
return this.items.join(' ')
}
module.exports = Stack
测试封装的栈结构
const Stack = require('./stack')
var stack = new Stack()
stack.push(1)
stack.push(2)
stack.push(3)
stack.push(4)
stack.push(5)
console.log(stack) //Stack { items: [ 1, 2, 3, 4, 5 ] }
stack.pop()
console.log(stack) //Stack { items: [ 1, 2, 3, 4 ] }
console.log(stack.peek()) //4
console.log(stack.isEmpty()) //false
console.log(stack.size()) //4
console.log(stack.print()) //1 2 3 4
栈结构的简单应用
利用栈结构的特点封装实现十进制转换为二进制的方法。
正整数转成二进制。要点一定一定要记住哈:除二取余,然后倒序排列,高位补零。
代码实现
function dec2bin(dec) {
let stack = new Stack()
while (dec > 0) {
//进栈
stack.push(dec % 2)
dec = Math.floor(dec / 2)
}
let bin = ""
while (!stack.isEmpty()) {
bin += stack.pop();
}
return bin
}
let bin = dec2bin(10)
console.log(bin) //1010