python实现的栈及算法应用(括号匹配、进制转换、前中后缀表达式)

栈的定义

class Stack:
    """
    items[0]为栈底
    """
    def __init__(self):
        self.items = []
    def isEmpty(self):
        return 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)

应用(一)括号匹配

只匹配小括号()
image

def parChecker(symbolString):
    """
    判断括号是否成对匹配
    :param symbolString:
    :return:
    """
    s = Stack()
    balanced = True
    index = 0
    while index < len(symbolString) and balanced:
        symbol = symbolString[index]
        if symbol == "(":
            s.push(symbol)
        else:
            if s.isEmpty():
                balanced = False
            else:
                s.pop()
        index += 1
    if s.isEmpty() and balanced:
        print("匹配成功", s.size())
    else:
        print("匹配失败", s.size())

通用{}[]()
image

def matches(open, close):
    opens = "([{"
    closes = ")]}"
    return opens.index(open) == closes.index(close)
# def parChecker2(symbolString):
#     """
#     判断括号是否成对匹配
#     :param symbolString:
#     :return:
#     """
#     s = Stack()
#     balanced = True
#     index = 0
#     while index < len(symbolString) and balanced:
#         symbol = symbolString[index]
         if symbol in "([{":
#             s.push(symbol)
#         else:
#             if s.isEmpty():
#                 balanced = False
#             else:
                 top = s.pop()
                 if not matches(top, symbol):
                     balanced = False
# 
#         index += 1
#     if s.isEmpty() and balanced:
#         print("匹配成功", s.size())
#     else:
#         print("匹配失败", s.size())

应用(二)进制转换-除n取余法

十进制转二进制

image

def divideBy2(d):
    """
    十进制 ==> 2进制
    :param d:
    :return:
    """
    s = Stack()
    while d > 0:
        b = d % 2
        s.push(b)
        d //= 2

    binstr = ""
    while s.size() > 0:
        binstr += str(s.pop())

    print(binstr)

十进制转十六以下任意进制

其实我们还可以扩展到n进制,多用一些字母代替数字即可。

image

def baseConverter(d):
    """
    十进制 ==> 16以下任意进制
    :return:
    """
    base = 16
    digits = "0123456789ABCDEF"
    s = Stack()
    while d > 0:
        b = d % base
        s.push(b)
        d //= base

    basestr = ""
    while s.size() > 0:
        basestr += str(s.pop())

    print(basestr)

应用(三)算术表达式转换&求值

术语
中缀表达式(运算符在数字中间): A+BC
全括号中缀表达式: ((A+(B
C))+D)
前缀表达式: +AB代表A+B
后缀表达式: AB+代表A+B
image
结论:距离操作数最近的操作符越优先参与运算

中缀表达式转后缀表达式

image
image

算法:
从左到右扫描中缀表达式
遇到操作数123...ABC...,直接输出
遇到左括号,压入栈s
遇到右括号,一直弹出栈顶操作符(并输出)直到遇到左括号
遇到操作符+-*/
(1)优先级大于栈顶操作符,压入栈s
(2)优先级小于栈顶操作符,一直弹出栈顶操作符(并输出)直到大于栈顶操作符后,压入栈s
扫描完毕,弹出栈s中所有操作符(并输出)
image

def infixTOpostfix(infixstr):
    """
    中缀表达式 ==> 后缀表达式
    :param infixstr:
    :return:
    """
    prec = {}
    prec['*'] = 3
    prec['/'] = 3
    prec['+'] = 2
    prec['-'] = 2
    prec['('] = 0

    s = Stack()
    pflist = []
    iflist = list(infixstr)

    for c in iflist:
        if c in "0123456789" or c in "ABCDEFJHIJKLMN":
            pflist.append(c)
        elif c == "(":
            s.push(c)
        elif c == ")":
            top = s.pop()
            while top != "(":
                pflist.append(top)
                top = s.pop()
        else:
            while (not s.isEmpty()) and prec[c] <= prec[s.peek()]:
                pflist.append(s.pop())
            s.push(c)

    while not s.isEmpty():
        pflist.append(s.pop())

    print(" ".join(pflist))

后缀表达式计算

image

image

image

算法:
从左到右扫描后缀表达式
遇到数字,压入栈s
遇到操作符,弹出两个操作数op2, op1,把计算得到的结果压入栈s
直到扫描完毕,此时栈中仅剩一个元素,即为计算结果

image

image

def doMath(c, op1, op2):
    if c == "+":
        return op1 + op2
    elif c == "-":
        return op1 - op2
    elif c == "*":
        return op1 * op2
    elif c == "/":
        return op1 / op2

def postfixEval(postfixstr):
    s = Stack()
    pflist = postfixstr.split()

    for c in pflist:
        if c in "0123456789":
            s.push(int(c))
        else:
            op2 = s.pop()  # 先弹出的是右操作数(计算减法和除法时操作数左右顺序有区分)
            op1 = s.pop()
            res = doMath(c, op1, op2)
            s.push(res)

    print(s.pop())
posted @ 2021-11-01 20:41  HUGBOY  阅读(172)  评论(0编辑  收藏  举报