Stack栈

  • 栈得基本实现
  • 使用栈解决一些常见的算法问题:括号匹配、进制转换

1、栈stack

  • 先进后出
  • 主要函数有:
    • Stack():创建一个新的空栈
    • push(item):将item 压入栈中
    • pop():将栈顶的元素弹出(删除)
    • peek():返回栈顶元素,但是不删除
    • isEmpty():返回一个布尔值,判断是否是空栈
    • size():返回栈中元素的个数
class Stack:
    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)
        
s = Stack()
print(s.isEmpty())

s.push(4)
s.push('dog')
print(s.peek())

s.push(True)
print(s.size())
print(s.isEmpty())

s.push(8.4)
print(s.pop())
print(s.pop())
print(s.size())
True
dog
3
False
8.4
True
2

2、使用栈来判断一个括号是否是正确匹配的

  • 例如:(()()()())、(((())))、(()((())()))等是正确的,()))是错误的
def parChecker(symbolString):
    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 = index + 1

    if balanced and s.isEmpty():
        return True
    else:
        return False

print(parChecker('((()))'))
print(parChecker('(()'))
True
False

3、括号匹配一个更广泛的应用,匹配对象不仅包含小括号,还包括中括号,大括号等

  • 例如:{ { ( [ ] [ ] ) } ( ) }
def parChecker(symbolString):
    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 balanced and s.isEmpty():
        return True
    else:
        return False
    
def matches(open, close):
    opens = "([{"
    closers = ")]}"
    return opens.index(open) == closers.index(close)
print(parChecker('{{([][])}()}'))
print(parChecker('[{()]'))
True
False

4、Divide by two 算法

  • 将一个十进制数转化为二进制
def divideBy2(decnumber):
    remStack = Stack()
    while decnumber > 0:
        rem = decnumber % 2
        remStack.push(rem)
        decnumber = decnumber // 2
    binString = ''
    while not remStack.isEmpty():
        binString =  binString + str(remStack.pop())
    return binString
print(divideBy2(42))
101010
  • 上述算法很容易转换成其他进制之间的转换:
def baseConverter(decNumber, base):
    digits = "0123456789ABCDEF"
    remStack = Stack()
    
    while decNumber > 0:
        rem = decNumber % base
        remStack.push(rem)
        decNumber = decNumber // base
    
    newString = ""
    while not remStack.isEmpty():
        newString = newString + digits[remStack.pop()]
    
    return newString
print(baseConverter(42, 2))
print(baseConverter(42, 8))
print(baseConverter(25, 16))
101010
52
19

5、表达式前缀、中缀、后缀转换

  • 概念介绍参考【这里

5.1、中缀转换为后缀

  • 例如: A + B * C >>> A B C * +,具体流程如下:
    • Create an empty stack called opstack for keeping operators. Create an empty list for output.
    • Convert the input infix string to a list by using the string method split.
    • Scan the token list from left to right.
    • If the token is an operand, append it to the end of the output list.
    • If the token is a left parenthesis, push it on the opstack.
    • If the token is a right parenthesis, pop the opstack until the corresponding left parenthesis is removed. Append each operator to the end of the output list.
    • If the token is an operator, *, /, +, or -, push it on the opstack. However, first remove any operators already on the opstack that have higher or equal precedence and append them to the output list.
    • When the input expression has been completely processed, check the opstack. Any operators still on the stack can be removed and appended to the end of the output list.
def infixToPostfix(infixexpre):
    prec = {"*":3, "/":3, "+":2, "-":2, "(":1 }
    opStack = Stack()
    postfixList = []
    tokenList = infixexpre.split()
    
    for token in tokenList:
        if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
            postfixList.append(token)
        elif token == "(":
            opStack.push(token)
        elif token == ")":
            topToken = opStack.pop()
            while topToken != '(':
                postfixList.append(topToken)
                topToken = opStack.pop()
        else:
            while (not opStack.isEmpty()) and (prec[opStack.peek()] >= prec[token]):
                postfixList.append(opStack.pop())
            opStack.push(token)
    while not opStack.isEmpty():
            postfixList.append(opStack.pop())
    return " ".join(postfixList)
    
print(infixToPostfix("A * B + C * D"))
print(infixToPostfix("( A + B ) * C - ( D - E ) * ( F + G )"))
print(infixToPostfix("( A + B ) * ( C + D )"))
print(infixToPostfix("( A + B ) * C"))
print(infixToPostfix("A + B * C"))
A B * C D * +
A B + C * D E - F G + * -
A B + C D + *
A B + C *
A B C * +

5.2、后缀表达式计算

  • 计算 456*+ = ?
def postfixEval(postfixExpr):
    operandStack = Stack()
    tokenList = postfixExpr.split()
#     print(tokenList)
    for token in tokenList:
        if token in "0123456789":
            operandStack.push(int(token))
        else:
            operand2 = operandStack.pop()
            operand1 = operandStack.pop()
            result = doMath(token, operand1, operand2)
            operandStack.push(result)
    return operandStack.pop()

def doMath(op, op1, op2):
    if op == "*":
        return op1 * op2
    elif op == "/":
        return op1 / op2
    elif op == "+":
        return op1 + op2
    else:
        return op1 - op2
print(postfixEval('7 8 + 3 2 + /'))
3.0
10 + 3 * 5 / (16 - 4)
11.25
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值