js数据结构系列 栈
1. 什么是栈
简单理解:
栈这种数据结构应该算是很简单的了吧,它的特点就是在于先进后出(LIFO)。如上图,一端为栈底,一端为栈顶。并且无论出栈还是入栈的操作都是发生在栈顶。
一个栈的数据结构应该具有以下操作:
- push 出栈
- pop 入栈
- peek 返回栈顶元素
- isEmpty 判空
- clear 清除栈中元素
- size 返回栈中元素个数
2. 实现一个栈
在js中,栈的实现是比较容易的。因为js的数组api封装了不少我们可以直接使用的方法。故这里我便不使用数组来创建栈了。因为那样没什么练习的意义,数组的push和pop方法也不是我们写的。
故换一种方法:(小心有留坑喔)
class Stack {
constructor() {
this.count = 0;
this.items = {};
}
push(e) {
this.items[this.count] = e;
this.count++;
}
pop() {
// 先判断是否为空栈
if (this.isEmpty()) {
return undefined;
}
this.count--;
const result = this.items[this.count];
delete this.items[this.count];
return result;
}
peek() {
if (this.isEmpty()) {
return undefined;
}
return this.items[this.count - 1];
}
clear() {
// 清除元素
// 长度重设
this.items = {};
// 注意这不是真正的清除,只是又创建了一个空的对象给了items
this.count = 0;
}
size() {
return this.count;
}
isEmpty() {
return this.count == 0;
}
toString() {
if (this.isEmpty()) {
return "";
}
let objString = `${this.items[this.count-1]}`;
for (let i = this.count - 2; i >= 0; i--) {
objString = `${objString},${this.items[i]}`;
}
return objString;
}
}
//部分测试代码
const stack = new Stack();
stack.push(5);
stack.push(8);
stack.push(10);
console.log(stack.peek());
console.log(stack);
首先我们先来创建一个Stack类。
解答:可能聪明的你已经发现了,我们写的这个栈的数据结构是不希望其他使用者可以直接操作我们的内部元素的。我们希望其他人只使用我们暴露出来的方法。这里便需要内部成员保护了。
方法一:最简单的一种实现是干掉内部成员,使用内部变量的方法。
class Stack {
let count=0;
let items={};
push(e) {
items[count] = e;
count++;
}
//其他方法
方法二:下划线命名约定
这个属实是自欺欺人的搞法。一部分开发者有着这样的约定。像这样this._items = {};
加个下划线就认为是这个类的私有属性了。嗯。。。
方法三:使用WeakMap
WeakMap的键是对象,值可以是任意数据类型。像下面WeakMap数据结构items是将this也就是将来这个类的实例当做了键,{}当做了值
举个小栗子:
const items = new WeakMap();
class Stack02 {
constructor() {
items.set(this, {});
}
push(element) {
const s = items.get(this);
s["aa"] = element;
}
pop() {
const s = items.get(this);
const r = s.aa;
return r;
}
// 其他方法
}
const aa = new Stack02();
aa.push(1);
console.log(aa);
console.log(aa.pop());
效果图:
看到没有明明我是先push然后打印输出再pop的。可是打印栈的结构时就只有一个空对象。这便实现了我们的要求。属性私有了,外界不可访问
3. 写一个栈的应用
栈的经典应用有很多,比如匹配括号了,十进制转二进制了,以及计算机中的内存栈了。
核心思想介绍完了本来是打算写了进制转换的栗子,有些晚了。说些思想吧。拿十进制转二进制来说,也就是余数法,即除2取余。但是最后余数必须是从下往上取。符合栈的特点。over