之前實現棧是透過 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
棧還是相對好理解的, 接下來整兩個關於用棧解決問題的經典案例.