數據結構之棧(stack)


1,棧的定義

  棧:先進后出的數據結構,如下圖所示,先進去的數據在底部,最后取出,后進去的數據在頂部,最先被取出。

      

  棧常用操作:   

s=Stack()         創建棧
s.push(item)      將數據item放在棧的頂部
s.pop()             返回棧頂部數據,並從棧中移除該數據
s.peek()           返回棧頂部數據,但不移除
s.size()            返回棧的大小
s.isEmpty()       返回棧是否為空                

  操作示例:

           

2,用python實現棧 

  通過python的list來實現棧,其定義如下面代碼所示。其中入棧和出棧操作也可以用insert(0,item)和pop(0),但其時間復雜度為O(n); 而append(item)和pop()時間復雜度為O(1)

class Stack(object):

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 isEmpty(self): return self.items==[]

3, 棧的應用

  3.1 判斷單個括號是否平衡:如下圖中的左括號和右括號是否依次匹配

    

              

    利用棧作為數據結構,左括號時入棧,右括號時出棧,相應的代碼如下:

from stackDemo import Stack

parentheses = ['((((((())','()))','(()()(()','()()()','(()()']

def check_balence(pString):
    s = Stack()
    for i in range(len(pString)):
        if pString[i]=='(':
            s.push(i)
        else:
            if not s.isEmpty():
                s.pop()
            else:
                return False
    return s.isEmpty()
for pt in parentheses:
    print check_balence(pt)

  3.2 判斷多種括號是否平衡:{ [ ( 和 ) ] }應依次匹配

       平衡示例:

       

       不平衡示例:

       

    實現代碼如下:

from stackDemo import Stack
def check_balance(sym_string):
    s= Stack()
    for i in range(len(sym_string)):
        symbol = sym_string[i]
        if symbol in '{[(':
            s.push(symbol)
        else:
            if not s.isEmpty():
                top = s.pop()
                if not match(top,symbol):
                    return False
            else:
                return False
    return s.isEmpty()
def match(open,close):
    opens = '{[('
    closes = '}])'
    return opens.index(open)==closes.index(close)
symbols = ['{ { ( [ ] [ ] ) } ( ) }','[ [ { { ( ( ) ) } } ] ]','[ ] [ ] [ ] ( ) { }', '( [ ) ]','( ( ( ) ] ) )','[ { ( ) ]']
for sym_string in symbols:
  sym_string
= sym_string.replace(' ','')
  
print check_balance(sym_string)

  3.3. 將十進制數轉化為二進制數

   過程:將十進制數不斷除2,將余數入棧,最后再一次彈出。

   代碼實現如下:

from stackDemo import Stack

def divideBy2(decNumber):
    s= Stack()
    while decNumber>0:
        remainder = decNumber%2
        s.push(remainder)
        decNumber = decNumber//2
    binStr = ''
    while not s.isEmpty():
        binStr = binStr + str(s.pop())
    return binStr
print divideBy2(8)

  3.4. 將十進制數轉化為二進制,八進制和十六進制數  

  (修改代碼便可以轉換十進制數為任何base的數字)

from stackDemo import Stack

def
baseConvetor(decNumber, base): s= Stack() while decNumber>0: remainder = decNumber%base s.push(remainder) decNumber = decNumber//base digits = '0123456789ABCDEF' binStr = '' while not s.isEmpty(): binStr = binStr + digits[s.pop()] if base==8: return "0"+binStr elif base==16: return "0x"+binStr else: return binStr print baseConvetor(30,2) print baseConvetor(30,8) print baseConvetor(30,16)

   3.5 算術表達式的轉換

      一般的算術表達式順序為Infix Expression,如下表所示,這種形式便於人類理解其執行順序,但對於電腦,Prefix Expression 和 Postfix Expression 兩種形式的表達式更容易理解。需要一個算法程序來完成Infix Expression 到 Prefix Expression 和 Postfix Expression的轉換。

    

    Infix Expression 到 Postfix Expression的轉換過程:    

      1,新建一個stack來存放運算符,一個list來存放輸出結果

      2,對infix expression進行遍歷,

        當碰到運算數時將其加入到list末尾

        當碰到左括號時,將其入棧,碰到右括號時,將棧中的內容依次移出並添加到list末尾,直到碰到相應的左括號停止

        當碰到運算符+ - * /時,將其入棧stack,但若棧中有優先度比其高或相同的運算符,先將其移出並添加到list末尾

      3,遍歷完成后,將棧中剩余內容依次彈出,添加到list末尾

    代碼實現如下:

def infixtopostfix(infix):
    prec={'(':1,'+':2, '-':2, '*':3, '/':3}
    infix_list = infix.split()
    s=Stack()
    postfix_list=[]
    for item in infix_list:
        if item in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or item in "0123456789":
            postfix_list.append(item)
        elif item=='(':
            s.push(item)
        elif item==')':
            top = s.pop()
            while top!='(':
                postfix_list.append(top)
                top = s.pop()
        else:
            while not s.isEmpty() and (prec[item]<=prec[s.peek()]):
                top = s.pop()
                postfix_list.append(top)
            s.push(item)
    while not s.isEmpty():
        postfix_list.append(s.pop())
    return ' '.join(postfix_list)

print infixtopostfix("A * B + C * D")
print infixtopostfix("( A + B ) * C - ( D - E ) * ( F + G )")
print infixtopostfix("( A + B ) * C")
print infixtopostfix("( A + B ) * ( C + D )")

    Postfix Expression的計算過程:

      1,創建一個stack來存放運算數

      2,遍歷Postfix Expression

        當碰到運算數時,將其入棧

        當碰到運算符時,出棧兩次,若第一次出棧為a,第二次出棧為b,計算 (b 運算符 a),並將結果入棧

      3,遍歷完成后,最終的計算結果在棧頂

    代碼實現如下:

def postfixEval(postfix):
    s = Stack()
    postfix_list = postfix.split()
    for token in postfix_list:
        if token in '0123456789':
            s.push(int(token))
        else:
            operand2 = s.pop()
            operand1 = s.pop()
            result = doMath(operand1,operand2,token)
            s.push(result)
    return s.pop()
def doMath(operand1,operand2,token):
    if token=='*':
        return operand1 * operand2
    elif token=='/':
        return operand1 / operand2
    elif token=='+':
        return operand1 + operand2
    else:
        return operand1 - operand2

print postfixEval('5 4 + 8 * 3 2 - 4 2 + * -')
print postfixEval('6 5 + 4 *')

    Infix Expression 到 Prefix Expression: 將Infix Expression 翻轉,左右括號互換,然后按infixtopostfix轉換,最后再進行翻轉?

    過程示例: "( A + B ) * C" — " C * ( B + A )"—"C B A + * "—" * + A B C"

 

參考:http://interactivepython.org/runestone/static/pythonds/BasicDS/WhatisaStack.html


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM