如何利用栈解决问题。html
Ref: 如何在程序中将中缀表达式转换为后缀表达式?算法
本文的引伸:如何手写语法分析器数据结构
“9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+”app
从左到右遍历中缀表达式的每一个数字和符号,post
如果数字就输出,即成为后缀表达式的一部分;spa
如果符号,则判断其与栈顶符号的优先级,.net
是右括号或优先级低于栈顶符号(乘除优先加减)code
一直到最终输出后缀表达式为止。orm
1. 初始化一空栈,用来对符号进出栈使用。htm
2. 第一个字符是数字9,输出9,后面是符号“+”,进栈。
3. 第三个字符是“(”,依然是符号,因其只是左括号,还未配对,故进栈。
4. 第四个字符是数字3,输出,总表达式为9 3,接着是“-”进栈。
5. 接下来是数字1,输出,总表达式为9 3 1,后面是符号“)”,此时,咱们须要去匹配此前的“(”,因此栈顶依次出栈,并输出,直到“(”出栈为止。此时左括号上方只有“-”,所以输出“-”,总的输出表达式为9 3 1 -
6. 接着是数字3,输出,总的表达式为9 3 1 - 3 。紧接着是符号“*”,由于此时的栈顶符号为“+”号,优先级低于“*”,所以不输出,进栈。
7. 以后是符号“+”,此时当前栈顶元素比这个“+”的优先级高,所以栈中元素出栈并输出(没有比“+”号更低的优先级,因此所有出栈),总输出表达式为 9 3 1 - 3 * +;而后将当前这个符号“+”进栈。也就是说,前6张图的栈底的“+”是指中缀表达式中开头的9后面那个“+”,而下图中的栈底(也是栈顶)的“+”是指“9+(3-1)*3+”中的最后一个“+”。
8. 紧接着数字10,输出,总表达式变为9 3 1-3 * + 10。
9. 最后一个数字2,输出,总的表达式为 9 3 1-3*+ 10 2
10. 因已经到最后,因此将栈中符号所有出栈并输出。最终输出的后缀表达式结果为 9 3 1-3*+ 10 2/+
整个过程,都充分利用了找的后进先出特性来处理,理解好它其实也就理解好了栈这个数据结构。
import logging class Stack: def __init__(self): self.items = [] def isEmpty(self): return self.items == [] def push(self, item): logging.info("Info: push {}".format(item)) self.items.append(item) def pop(self): if True == self.isEmpty(): logging.info("Info: it's empty.") return None return self.items.pop() def peek(self): if True == self.isEmpty(): logging.info("Info: it's empty.") return None return self.items[-1] def size(self): return len(self.items) def __str__(self): return "{}".format(self.items) logging.basicConfig(level=logging.INFO) # “9+(3-1)*3+10/2” --> “9 3 1-3*+ 10 2/+” def infixToPostfix(infixexpr): prec = {} prec["*"] = 3 prec["/"] = 3 prec["+"] = 2 prec["-"] = 2 prec["("] = 1 # 只有符号才须要“栈' opStack = Stack() postfixList = [] tokenList = infixexpr.split() for token in tokenList: if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789": postfixList.append(token) elif token == '(': opStack.push(token) elif token == ')': # do...while, 把括号区间的符号都输出 while True: topToken = opStack.pop() if topToken == '(': break postfixList.append(topToken) 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 )"))
End.