前言 :
在说栈之前先来说一下我们比较熟悉的 数组,JS 中已经对数组做了很好的封装,可以通过一些 API 方法实现指定位置插入,指定元素删除,还实现了自动扩容的功能等。在其他的语言中,如 JAVA。数组作为底层数据结构,存在无法自动扩容等问题,在 ArrayList 等中,会使用新建更大的数组去替换原数组的方式去实现。总而言之,从数据结构来说,数组的插入和删除操作很耗性能,比较复杂的,因为要考虑到其他元素下标值得改变。但是数组又有它自己独特得优势,可以通过下标查找指定元素(高效)。后续链表得出现,弥补了数组插入和删除,不自动扩容等操作。但是它不利于查找(线性查找,低效)。
- 栈的概念 ?
我们知道 数组是一种线性结构,并且可以在数组的任意位置插入和删除数据,有时候,我们为了实现某些功能,必须对这种任意性加以限制。栈和队列就是比较常见的受限的线性结构。
- 栈的特点 ?
栈有底部(栈底),底部封闭,只能在顶部(栈顶)添加或者删除元素。其中添加元素称为进栈,删除元素称为出栈。它具有是 后进先出(LIFO)的特性。
- 栈的使用场景举例 ?
- 函数调用栈 : A 函数调用了 B 函数,B 函数调用了 C 函数, C 函数又调用了 D 函数。栈结构(A-B-C-D),A 函数处于栈底,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
解析:答案为 C ,当 3 出栈的时候,(6,5,4,3)已经确保在栈中。当 3 和 4 满足后,6 出栈,是不可能的,因为之前栈顶元素已经确定为 5,应该先弹出 5。
- 栈的实现 ?
实现栈结构,可以通过 数组实现,也可以通过 链表实现。下面去演示用数组去实现的过程。(JS)
// 封装栈类
function Stack(){
// 栈中的元素
this.items = [];
// 栈中的操作
//1,进栈操作
Stack.prorotype.push = function(el){
this.items.push(el);
}
//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.toString = function(){
var resultStr = '';
for(var i=0; i<this.items.length; i++){
resultStr += this.items[i] + '';
}
return resultStr;
}
}
// 栈的使用
var s = new Stack();
stack.push(10);
stack.push(34);
stack.push(56);
stack.push(78);
alert(stack);
stack.pop();
alert(stack);
alert(stack.peek());
alert(stack.isEmpty());
alert(stack.size());
alert(stack.toString());
- 栈的使用实例——十进制转换为二进制 ?
// 封装栈类
function Stack(){
//栈中的元素
this.items = [];
//栈中的方法
//1,元素进栈
Stack.prototype.push = function(el){
this.items.push(el);
}
//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.toString = function(){
var resultStr = '';
for(var i=0; i<this.items.length; i++){
resultStr += this.items[i] + '';
}
return resultStr;
}
}
// 转换函数
function convert(num){
// 使用栈
var s = new Stack();
// 当num小于等于0的时候终止循环
while(num > 0){
// 把每次num%2的结果压入栈中
s.push(num%2);
// 每次num更新数值为,num/2d的整数
num = Math.floor(num/2);
}
var result = '';
while(!s.isEmpty()){
result += s.pop();
}
return result;
}
console.log(convert(10)); //1010