線性結構 佇列與棧

小馬就是神發表於2019-02-16

線性結構 佇列與棧

棧(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;
}

相關文章