為什麼要學習資料結構?
相信大家都聽過一句話程式=資料結構+演算法,資料結構和演算法是脫離程式語言而存在的,不同的語言有不同的實現版本,但內在的邏輯卻不會有變化,所體現的程式設計思想不會有變化。雖然前端可能對資料結構和演算法的要求沒有那麼高,但是作為一個程式設計師資料結構是我們應該掌握的基本知識。
1、棧的定義
棧是一種特殊的線性表,我們只能夠在棧頂對其進行操作,有著先進後出的特點
2、棧的實現
實現棧可以用陣列來儲存資料,這是最簡單的方式。
// 定義一個stack類
function Stack() {
let items = [] // 用於儲存資料,
}
複製程式碼
2.1定義棧的一些常用的方法
- push 新增一個元素到棧頂
- pop 彈出棧頂元素
- top 返回棧頂元素,注意,不是彈出
- isEmpty 判斷棧是否為空
- size 返回棧裡元素的個數
- clear 清空棧
你還可以定義其他你認為你將要用到的方法,這些只是一些常用的方法
push
// 新增一個元素到棧頂
this.push = (data) => {
items.push(data)
}
複製程式碼
pop
// 刪除棧頂元素
this.pop = () => {
return items.pop()
}
複製程式碼
top
// 返回棧頂元素
this.top = () => {
return items[items.length - 1]
}
複製程式碼
isEmpty
// 檢查棧是否為空
this.isEmpty = () => {
return items.length === 0
}
複製程式碼
size
// 返回棧的大小
this.size = () => {
return items.length
}
複製程式碼
clear
// 清空棧
this.clear = () => {
items = []
}
複製程式碼
最終程式碼
function Stack() {
let items = []
this.push = (data) => {
items.push(data)
}
this.pop = () => {
return items.pop()
}
this.top = () => {
return item[items.length - 1]
}
this.isEmpty = () => {
return items.length === 0
}
this.size = () => {
return items.length
}
this.clear = () => {
items = []
}
}
複製程式碼
3、棧的應用
3.1、檢查括號的合法性
下面的字串中包含小括號,請編寫一個函式判斷字串中的括號是否合法,所謂合法,就是括號成對出現
- sdf(ds(ew(we)rw)rwqq)qwewe 合法
- (sd(qwqw)sd(sd)) 合法
- ()()sd()(sd()fw))( 不合法
思路分析
括號存在巢狀關係,也存在並列關係,如果是用陣列儲存這些括號,然後再想辦法一對一對的抵消掉,似乎是一個可行的辦法,可是如何判斷一個左括號對應的是哪個右括號呢?站在陣列的肩膀上思考這個問題,就陷入到一種無從下手的絕望之中。
現在,我們站在棧的肩膀上思考這個問題,解題的步驟就非常簡單,我們可以使用for迴圈遍歷字串的每一個字元,對每個字元做如下的操作:
- 遇到左括號,就把左括號壓如棧中
- 遇到右括號,判斷棧是否為空,為空說明沒有左括號與之對應,缺少左括號,字串括號不合法,如果棧不為空,則把棧頂元素移除,這對括號抵消掉了
當for迴圈結束之後,如果棧是空的,就說明所有的左右括號都抵消掉了,如果棧裡還有元素,則說明缺少右括號,字串括號不合法。
程式碼實現
function is_leagl(str) {
let stack = new Stack()
for(let i = 0; i < str.length; i ++) {
let item = str[i]
if(item === '(') { // 左括號入棧
stack.push(item)
} else if (item === ')') { // 右括號
if(stack.isEmpty()) { // 檢查棧是否為空
return false
} else { // 不為空彈棧
stack.pop()
}
}
}
}
複製程式碼
棧還有其他很多的應用比如:1、計算代數式;2、構造表示式;3、用於函式得呼叫等等。
4、最後
在學習了棧之後瞭解到了它的方便之處,雖然是基於資料來實現的,但是在某些場景使用起來比資料更加方便快捷。後面會繼續學習佇列、連結串列、樹、圖等其他資料結構來豐富自己的知識。