来源:【程序员成功】公众号
栈--数组篇
引入
(你遇到的使用栈的场景有哪些?)
生活中去饭堂打饭,我们需要自己去拿托盘,托盘的摆放是层叠的,最先放在下面的托盘反而是最后被拿起来的
//个人认为这是一个非常贴近生活的形容栈的一个例子
什么是栈?
栈是一种数据结构,其本质是一个数组,只不过栈在数组的基础上加了一些限制 (这可谓是非常粗浅的理解了😁)
栈长什么样?
结合刚说的栈的本质是数组,所以说栈其实就是由一长串字符串组成的一条长龙
栈的规则是什么?
唯一与数组不一样的就是不能随心所欲的插队,栈的排队方式有着自己的规则
特性:后进先出(Last in first out),也就是说栈是一种遵从后进先出原则的有序集合
后进先出,很好理解吧,就是最先进去的,最后出来,最后进去的,反而最先出来
如何使用
- 创建一个栈
- 常用方法
- 使用
//使用ES6的Class关键字
class Stack{
constructor(){
//用一个lists数组保存栈的数据
this.lists = [] //默认空数组
}
//常用方法
/*
1:入栈
2:出栈
3:清空栈
4:判断栈是否有元素
5:栈的元素数量
6:返回栈顶元素
*/
push(item){
this.lists.push(item)
}
pop(){
//弹出栈顶元素
this.lists.pop()
}
clear(){
this.lists = []
}
isEmpty(){
return this.lists.length == 0
}
size(){
return this.lists.length
}
peek(){
this.lists[this.lists.length - 1]
}
}
const s = new Stack()
console.log(s.isEmpty());
s.push('河源')
s.push('东莞')
console.log(s.size());
s.pop('河源')
console.log(s.size());
console.log(s.isEmpty());
使用数组形式的栈有很大的弊端,数组的操作本质都是要遍历数组,直到查到目标,如果当数组的数据非常多时,查询的效率就会很低,加上数组会保证元素的排列顺序,因此也会占用更多的内存
为了解决上述问题,引入JavaScript对象
栈--JavaScript对象篇
直接上代码
class Stack{
constructor(){
//count表示栈元素长度
this.count = 0;
//保存栈的元素
this.lists = {};
}
//同数组篇的方法是一样的
push(value){
this.lists[this.count] = value
this.count++
}
pop(){
if(this.isEmpty()){
return undefined
}
this.count--
//找到栈顶的元素,先用一个变量把值存起来
let list = this.lists[this.count]
//然后再删除
delete this.lists[this.count]
//最后返回那个被删除的元素
return list
}
isEmpty(){
return this.count == 0
}
size(){
return this.count
}
clear(){
this.count = 0;
this.lists = {}
}
peek(){
if(this.isEmpty()){
return undefined
}
return this.lists[this.count-1]
}
//实现toString方法
/*
数组提供了默认的toString方法,当想用字符串的形式展现数组时,数组可以直接调用toString方法
但是对象的toString方法返回的都是[object object],
所以想要实现字符串形式展现,需要自己写一个toString方法,按照数组的格式返回
ES6给我们提供了对象直接转成数组的方式
*/
toString(){
//对象转化为数组,通过调用Object.value()
let arr = Object.values(this.lists)
return arr.toString()
}
}
let s = new Stack()
s.push('上海')
s.push('北京')
s.push('河源')
s.push('东莞')
console.log(s.size());
console.log(s);
console.log(s.isEmpty());
s.pop()
console.log(s);
console.log(s.toString());
运行截图:
力扣 20题:有效括号
//解法一
var isValid = function(s){
const stack = [];
for(let i = 0; i < s.length; i++){
const x = s[i]
if(x === "(" || x === "[" || x === "{"){
//入栈
stack.push(x)
} else{
if(stack.length == 0){
return false
}
//去除栈顶元素与x作比较
const top = stack[stack.length-1]
if(top === "(" && x === ")" ||top === "{" && x === "}" || top === "[" && x === "]" ){
stack.pop()
} else{
return false
}
}
}
return stack.length == 0
};
//解法二:Map
var isValid = function(s){
//先判断s的长度是否为偶数,若为奇数,则说明一定会有一个括号未匹配
if(s.length % 2 === 1){
return false;
}
const map = new Map([
[")","("],
["]","["],
["}","{"]
])
const stack = []
for(let x of s){
if(map.has(x)){
if(!stack.length || stack[stack.length-1] !== map.get(x)){
return false
}
stack.pop()
} else{
stack.push(x)
}
}
return !stack.length
}