數據結構[Python--Stack] 的應用

難得有些許空閒,看一下Python的數據結構--Stack,現將幾個典型示例進行總結!

一、什麼是棧

     棧是一個有序集合,根據其特性可以稱爲"先進後出"或"後進先出", 其中添加或刪除都發生在同一端,這一端被稱爲"棧頂",與其對應的叫"棧底"。

    棧的底部很重要,因爲其底部存儲的數據是時間最長的,最近的添加項總是最先會彈出,這種排序原則有時被稱爲"LIFO"

二、棧

1. 棧的可用操作

  • Stack() 創建一個空的新棧。 它不需要參數,並返回一個空棧。

  • push(item)將一個新項添加到棧的頂部。它需要 item 做參數並不返回任何內容。

  • pop() 從棧中刪除頂部項。它不需要參數並返回item 。棧被修改。

  • top() 從棧返回頂部項,但不會刪除它。不需要參數。 不修改棧。

  • isEmpty()測試棧是否爲空。不需要參數,並返回布爾值。

  • size() 返回棧中的item 數量。不需要參數,並返回一個整數。

  • clear 清空棧,沒有返回值

2. 利用Python 的內置的數據結構List實現棧全部操作

class Stack():
    def __init__(self):
        self.itmes = []
    def isEmpty(self):
        return self.itmes == []
    def clear(self):
        del self.itmes[:]
    def push(self, item):
        self.items.append(item)
    def pop(self):
        return self.itmes.pop()
    def top(self):
        return self.items[-1]
    def size(self):
        return len(self.itmes)

3. 棧的使用示例

3.1 進制轉換

class Stack():
    def __init__(self):
        self.itmes = []
    def isEmpty(self):
        return self.itmes == []
    def clear(self):
        del self.itmes[:]
    def push(self, item):
        self.items.append(item)
    def pop(self):
        return self.itmes.pop()
    def top(self):
        return self.items[-1]
    def size(self):
        return len(self.itmes)
def divideBy2(decNumber, base):
    remstack = Stack()
    while decNumber > 0:
        rem = decNumber % base
        remstack.push(rem)
        decNumber = decNumber // base
    binString = ""
    while not remstack.empty():
        binString = binString + str(remstack.pop())
    return binString
if __name__ == '__main__':
    print(divideBy2(42, 2))

說明: 這是用List結構來實現的"棧", 同樣我們可以自己寫一個棧

3.2 自己寫棧

class Node:
    def __init__(self, value):
        self.value = value
        self.next = None
class Stack:
    def __init__(self):
        self.top = None
    def push(self, value):
        node = Node(value)
        node.next = self.top
        self.top = node
    def pop(self):
        node = self.top
        self.top = node.next
        return node.value
s = Stack()
s.push(3)
s.push('ac')
s.push('er')
s.pop()
s.push(5)

說明

  1. 上面所定義的棧,是由top指針指向一個完整的Node實例

  2. 定義一個棧,使用指針控制其讀取的位置。

3.3 棧應用--前綴表達式(波蘭式)

from __future__ import division
class Node():
    def __init__(self, value):
        self.value = value
        self.next = None
class StackNode():
    def __init__(self):
        self.top = None
    def push(self, value):
        node = Node(value)
        node.next = self.top
        self.top = node
    def pop(self):
        node = self.top
        self.top = node.next
        return node.value
def compute_exec(op, ov1, ov2):
    def add(ov1, ov2):
        return ov1 + ov2
    def sub(ov1, ov2):
        return ov1 - ov2
    def mul(ov1, ov2):
        return ov1 * ov2
    def div(ov1, ov2):
        return ov1 / ov2
    ops = {add: '+', sub: '-', mul: '*', div: "/"}
    for k, v in ops.items():
        if v == op:
            ret = k(ov1, ov2)
            stack1.push(ret)
            break
def perfix_reverse(string):  # reverse
    tmp = ''
    for s in string[::-1]:
        if s == "(":
            tmp += ")"
        elif s == ")":
            tmp += "("
        else:
            tmp += s
    return tmp
def infix_to_prefix(string):
    opt = ''
    string_tmp = perfix_reverse(string)
    for i in string_tmp:  #  前綴表達式
        if i.isdigit():
            opt = i + opt
        elif i != ')':
            stack1.push(i)
        elif i == ")":
            opt = stack1.pop() + opt
            stack1.pop()
    for s in opt[::-1]:
        if s.isdigit():
            stack1.push(s)
        else:
                op1 = s
                ov1 = stack1.pop()
                ov2 = stack1.pop()
                compute_exec(op1, int(ov1), int(ov2))  # compute result 
                continue
    return opt, stack1.pop()
if __name__ == '__main__':
    stack1 = StackNode()  # 操作符
    infix = ['((3+4)*2)', '((3+(4*2))-1)', '(5*(1+2))']
    for i, v in enumerate(infix):
        print infix[i], "==>", infix_to_prefix(v)

說明:

  1. 前綴表達式就是說操作符位於操作數之前

  2. 表達式從右向左依次解析。將數值壓棧,遇到符號將棧頂的操作數與次位置彈出進行計算,結果再次入棧,直到表達式解析完成。

3.4 棧應用--後綴表達式(逆波蘭式)

class Node():
    def __init__(self, value):
        self.value = value
        self.next = None
class StackNode():
    def __init__(self):
        self.top = None
    def push(self, value):
        node = Node(value)
        node.next = self.top
        self.top = node
    def pop(self):
        node = self.top
        self.top = node.next
        return node.value
def compute_exec(op, ov1, ov2):
    def add(ov1, ov2):
        return ov1 + ov2
    def sub(ov1, ov2):
        return ov1 - ov2
    def mul(ov1, ov2):
        return ov1 * ov2
    def div(ov1, ov2):
        return ov1 / ov2
    ops = {add: '+', sub: '-', mul: '*', div: "/"}
    for k, v in ops.items():
        if v == op:
            ret = k(ov1, ov2)
            stack1.push(ret)
            break
def postfix(expr):
    for s in expr:
        if s.isdigit():
            stack2.push(s)
        elif s != ")":
            stack1.push(s)
        elif s == ")":
            top = stack2.pop()
            snext = stack2.pop()
            stack2.push(''.join([snext, top, stack1.pop()]))
            stack1.pop()
    post_expr = stack2.pop()
    for i in post_expr:
        if i.isdigit():
            stack1.push(i)
        else:
            op = i
            top = stack1.pop()
            snext = stack1.pop()
            compute_exec(op, int(snext), int(top))
    return post_expr, stack1.pop()
if __name__ == '__main__':
    stack1 = StackNode()  # 操作符
    stack2 = StackNode()  # 操作數
    exprs = ['((3+(4*2))-1)', '((3*4)+(3/2))']
    for e in exprs:
        print e, "==>", postfix(e)

說明:

  1.  後綴表達式就是說操作符位於操作數之後。

  2.  表達式從左向右依次解析。將數值壓棧,遇到符號將棧頂的操作數與次位置彈出進行計算[次位操作數 棧頂操作數 操作符 ],結果再次入棧,直到表達式解析完成

  3.  計算表達式結果時同樣是[次位操作數 操作符 棧頂操作數 ]


四、總結

  1. 以上示例都可以通過http://pythontutor.com/visualize.html#mode=edit 查看程序運行的每一步

  2. 本文參考於https://www.gitbook.com/book/facert/python-data-structure-cn/details

  3. 以上後兩個示例代碼基於自己理解所寫,可能存在bug

  4. 後兩個示例的缺點是沒有寫表達式合法性的檢查,表達式的優先級(如表達式無括號可能會導致程序異常)

  5. 此處僅是對棧的一此粗淺理解及應用。


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章