栈结构-对象形式
之前实现栈是通过 js 数组实现的, 其实也可以用对象形式来实现.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
}
向栈顶插入元素
即通过对象新增属性 count
和元素值 item
的形式即可.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// 入栈
push(item) {
this.obj[this.count] = item
this.count += 1
}
}
用数字或者变量字符啥的作为对象的 key
会自动转换为字符的. 假设我们 push 两个元素 666, 888 进去.
const stack = new Stack()
stack.push(666)
stack.push(888)
则在内部 obj
的值和 count
属性显示如下:
obj = {
0: 666,
1: 888
}
判断栈是否为空
即通过判断 count
的值是否为 0 即可, 顺便实现栈的 size
方法, 本质是同一个东西.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// 栈是否为空
isEmpty() {
return this.count == 0
}
// 栈的大小
size() {
return this.count
}
}
从栈顶移除元素
- 当栈为空时, 返回
undefined
即可 - 当栈有值, 因为底层对象的键是通过
count
属性从 0 开始递增的, 则长度为count - 1
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
isEmpty() {
return this.obj.count == 0
}
// 出栈
pop() {
if (this.isEmpty()) return undefined
this.count= this.count - 1
const item = this.obj[this.count]
delete this.obj[this.count]
return item
}
}
这里的栈顶元素的键要根据 count -1
还是举例说明一下:
const obj = {}
let count = 0
obj[count] = 1
count += 1
obj[count] = 2
count += 1
obj[count] = 3
count += 1
console.log(obj, count);
PS F:\algorithms> node .\stack_object
{ '0': 1, '1': 2, '2': 3 } 3
可以看到, count 是3, 但最后一个元素是 2 , 这样就很清晰了.
也顺带来简单测试一下入栈, 出栈的操作是否合适.
const stack = new Stack()
stack.push(666)
console.log(stack.pop());
console.log(stack.size());
console.log(stack.isEmpty());
PS F:\algorithms> node .\stack_object
666
0
true
查看栈顶元素
即实现 peek
方法, 返回栈顶元素但不做任何操作.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// 查看栈顶元素
peek() {
if (this.isEmpty()) return undefined
return this.obj[this.count -1]
}
}
清空栈元素
最简单的方法是让其指向空对象, 或者通过不断地 pop
.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// 清空栈
clear() {
this.count = 0
this.obj = {}
}
// 当然也可以不断地 pop
clear2() {
while (! this.isEmpty()) {
this.pop()
}
}
}
栈的 toString 方法
在数组版本的栈中, 可以直接调用其 toString
方法, 而当前的对象版本则可以手动实现一下.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// toString 方法
toString() {
if (this.isEmpty()) return ''
let objString = `${this.obj[0]}`
for (let i = 1; i < this.count; i++) {
objString = `${objString}, ${this.obj[i]}`
}
return objString
}
}
至此, 我们用 js 对象作为底层实现的栈也就好了. 但注意这是有缺陷的, 就是在于 count
和 ojb
这两个属性是得不到保护的. 具体咋弄就不讨论了, 主要还是以学习为主的, 自己玩.
class Stack {
constructor() {
// 用一个 count 属性来记录栈的大小
this.count = 0
this.obj = {}
}
// 入栈
push(item) {
this.obj[this.count] = item
this.count += 1
}
// 栈是否为空
isEmpty() {
return this.count == 0
}
// 栈的大小
size() {
return this.count
}
// 出栈
pop() {
if (this.isEmpty()) return undefined
this.count= this.count - 1
const item = this.obj[this.count]
delete this.obj[this.count]
return item
}
// 查看栈顶元素
peek() {
if (this.isEmpty()) return undefined
return this.obj[this.count -1]
}
// 清空栈
clear() {
this.count = 0
this.obj = {}
}
// 当然也可以不断地 pop
clear2() {
while (! this.isEmpty()) {
this.pop()
}
}
// toString 方法
toString() {
if (this.isEmpty()) return ''
let objString = `${this.obj[0]}`
for (let i = 1; i < this.count; i++) {
objString = `${objString}, ${this.obj[i]}`
}
return objString
}
}
// test
const stack = new Stack()
stack.push(666)
console.log(stack.pop());
console.log(stack.size());
console.log(stack.isEmpty());
stack.push(888)
stack.push(999)
stack.push(111)
console.log('栈元素是: ', stack.toString())
console.log('栈顶元素是: ', stack.peek());
PS F:\algorithms> node .\stack_object
666
0
true
栈元素是: 888, 999
栈还是相对好理解的, 接下来整两个关于用栈解决问题的经典案例.
耐心和恒心, 总会获得回报的.