Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情。
1、先来一道面试题开开胃
实现一个栈数据结构,接口如下,请实现该类的 in、out、top、size 函数
class Stack {
constructor() {}
in(value) {
// 你的代码
}
out() {
// 你的代码
}
top() {
// 你的代码
}
size() {
// 你的代码
}
}
// 要求当执行下列代码时,能输出预期的结果
const stack = new Stack()
stack.in('x')
stack.in('y')
stack.in('z')
stack.top() // 输出 'z'
stack.size() // 输出 3
stack.out() // 输出 'z'
stack.top() // 输出 'y'
stack.size() // 输出 2`
小伙伴们可以自己先思考一下怎么实现,再看后面的解析
2、简单的了解一下栈
栈是一种特殊的线性表,其实只允许在固定的一端进行插入或删除操作。进行数据插入和删除的一端称为栈顶,另一端称为栈底。不含任何元素的栈称为空栈,栈又称为 后进先出的线性表。
一般对栈的操作有:入栈、出栈、获取栈顶元素、获取栈元素个数、打印栈等等。开头的面试题基本就囊括了大部分栈操作。
3、该如何实现面试题
第一种方案:使用数组方法实现(最容易想到也最容易实现)
class Stack {
constructor() {
this.item = [] //声明数组来存数据
}
in(value) {
this.item.push(value)
}
out() {
return this.item.pop()
}
top() {
return this.item[this.item.length - 1]
}
size() {
return this.item.length
}
}
这种方案里面的成员变量数组item是公有的,可能会被外部访问操作,从而破坏栈数据结构。比如:
const stack = new Stack()
stack.item.push(555)
第二种方案:使用Symbol来限定变量的作用域
let _items = Symbol()
class Stack {
constructor() {
this[_items] = []
}
in(value) {
this[_items].push(value)
}
out() {
return this[_items].pop()
}
top() {
return this[_items][this[_items].length - 1]
}
size() {
return this[_items].length;
}
}
这种方案不能再通过Stack类的实例来访问其内部成员变量,但是仍然可以有方法来访问_items。比如:
const stack = new Stack()
const objectSymbols = Object.getOwenPropertySymbols(stack)
第三种方案:使用WeakMap数据类型实现
const items = new WeakMap()
class Stack {
constructor() {
items.set(this, [])
}
in(value) {
const s = items.get(this)
s.push(element)
}
out() {
const s = items.get(this)
return s.pop()
}
top() {
const s = items.get(this)
return s[s.length - 1]
}
size() {
return items.get(this).length;
}
}
这种方案实现也还是有弊端的,具体有啥弊端请小伙伴评论区告诉我吧(嘻嘻,作业哟)。
当然有小伙伴有更好的实现方案也希望你可以不吝赐教。