線性結構 佇列與棧
棧
棧(Stack)是一種遵循先進後出(LIFO)原則的有序列表,新新增或待刪除的元素都儲存在棧的一端,這一端被稱作為棧頂,另一端被稱作為棧底。在棧裡,新元素都靠近棧頂,舊元素都靠近棧底。
棧的操作
方法 | 操作 |
---|---|
push | 新增新元素到棧頂 |
pop | 移除並返回棧頂元素 |
peek | 返回棧頂元素 |
size | 返回棧大小 |
clear | 移除棧內所有元素 |
isEmpty | 判斷棧是否為空 |
Python實現棧
# python3
class Stack:
def __init__(self):
self.items = []
def push(self, item):
self.items.append(item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
def size(self):
return len(self.items)
def clear(self):
self.items = []
def is_empty(self):
return self.items == []
JavaScript實現棧
// ES6
class Stack {
constructor() {
this.items = [];
}
push(item) {
this.items.push(item);
}
pop() {
return this.items.pop();
}
peek() {
return this.items[-1];
}
size() {
return this.items.length;
}
clear() {
this.items = [];
}
isEmpty() {
return this.items.length === 0;
}
}
佇列
佇列(Queue)是一種遵循先進先出(FIFO)原則的有序列表。佇列在尾部新增新元素,從頂部移除元素。最新新增的元素必須排列在佇列的末尾。
佇列操作
方法 | 操作 |
---|---|
enqueue | 新增新元素到佇列尾部 |
dequeue | 移除並返回隊首元素 |
front | 返回隊首元素 |
size | 返回佇列大小 |
clear | 移除佇列內所有元素 |
isEmpty | 判斷佇列是否為空 |
Python實現佇列
# python3
class Queue:
def __init__(self):
self.items = []
def enqueue(self, item):
self.items.append(item)
def dequeue(self):
return self.items.pop(0)
def front(self):
return self.items[0]
def size(self):
return len(self.items)
def clear(self):
self.items = []
def is_empty(self):
return self.items == []
JavaScript實現佇列
// ES6
class Queue {
constructor() {
this.items = [];
}
enqueue(item) {
this.items.push(item);
}
dequeue() {
return this.items.shift();
}
front() {
return this.items[0];
}
size() {
return this.items.length;
}
def clear() {
this.items = [];
}
isEmpty () {
return this.items.length === 0;
}
}
棧的應用
迴文檢索
迴文是指一種現象,一個單詞、短語或數字,從前往後和從後往前都是一樣的。
# 單詞
dad
racecar
# 數字
1001
使用棧,可以輕鬆判斷一個字串是否是迴文。將字串的每個字元按順序亞入棧。當字串中的字元都入棧後,棧內就儲存了一個反轉後的字串。通過彈出棧內每個字母可以得到一個新字元,只需要比較兩個字串即可。
# python3
def palindrome(word):
s = Stack()
word = str(word)
rword = ``
for i in word:
s.push(i)
while not s.is_empty():
rword += s.pop()
return word == rword
// ES6
function palindrome(word) {
let s = new Stack();
word = String(word);
let rword = ``;
for (i of word) {
s.push(i);
}
while (! s.isEmpty()) {
rword += s.pop();
}
return word === rword;
}
簡單括號匹配
在表示式中,括號必須以匹配的方式出現。括號匹配意味著每個開始符號具有相應的結束符號,並且括號能被正確巢狀。
(5+6)*(7+8)/(4+3) # 括號匹配
(2+3)+24/12+(4-2 # 括號不匹配
棧可以用來判斷一個表示式中的括號是否匹配。從空棧開始,從左到右處理表示式。如果一個符號是一個開始符號,將其作為一個訊號,對應的結束符號稍後會出現。另一方面,如果符號是結束符號,彈出棧,只要彈出棧的開始符號可以匹配每個結束符號,則括號保持匹配狀態。如果任何時候棧上沒有出現符合開始符號的結束符號,則字串不匹配。最後,當所有符號都被處理後,棧應該是空的。
# python3
def par_checker(expression):
s = Stack()
balanced = True
index = 0
while index < len(expression) and balanced:
symbol = expression[index]
if symbol == `(`:
s.push(symbol)
elif symbol == `)`:
item = s.pop()
if item != `(`:
balanced = False
index += 1
return balanced and s.is_empty()
// ES6
function parChecker(expression) {
let s = new Stack();
let balanced = true;
let index = 0;
while (index < expression.length && balanced) {
symbol = expression[index]
if (symbol === `(`) {
s.push(symbol);
} else if (symbol === `)`) {
let item = s.pop();
if (item !== `(`) {
balanced = false;
}
}
index += 1;
}
return balanced && s.isEmpty();
}
進位制轉換
在生活中,我們主要使用十進位制數。但在計算科學中,二進位制非常重要,因為計算機裡的內容都是用二進位制數字表示的(0和1)。如果沒有進位制轉化的能力,與計算機交流就會非常困難。
要把十進位制數轉化成二進位制的演算法,將十進位制數與2相除,並取餘數。
10 => 1010
10/2 = 5, rem = 0
5/2 = 2, rem = 1
2/2 = 1, rem = 0
1/2 = 0, rem = 1
Python實現
# python3
def divide_by2(dec_str):
s = Stack()
dec_num = int(dec_str)
bin_str = ``
while dec_num > 0:
rem = dec_num % 2
s.push(rem)
dec_num //= 2
while not s.is_empty():
bin_str += str(s.pop())
return bin_str
同理,我們可以推匯出十進位制數轉化八進位制和十六進位制演算法。以下是完整的進位制轉換演算法。
# python3
def base_converter(dec_str, base):
s = Stack()
digits = "0123456789ABCDEF"
dec_num = int(dec_str)
new_str = ``
while dec_num > 0:
rem = dec_num % base
s.push(rem)
dec_num //= base
while not s.is_empty():
new_str += digits[s.pop()]
return new_str
// ES6
function baseConverter(decStr, base) {
let s = new Stack();
let digits = "0123456789ABCDEF";
let decNum = Number(decStr);
let newStr = ``;
while (decNum > 0) {
rem = decNum % base;
s.push(rem)
decNum = Math.floor(decNum/base);
}
while (! s.isEmpty()) {
newStr += digits[s.pop()]
}
return newStr;
}