中缀转前缀
eg: (3+5)*7
我们按照如下步骤将其转换为前缀表达式:
由于前缀表达式要求运算符在操作数之前,所以必须从后向前扫描中缀表达式
定义prefix=[]
- 扫描到7,一个操作数什么也干不了,所以prefix=[7]
- 扫描到*,此时什么也干不了,先记住*号
- 扫描到5,5和7之间由于有括号,不能算乘法,所以prefix=[5,7]
- 扫描到+,由于括号的存在,此时什么也干不了,记住+号
- 扫描到3,由于3和5可以算加法,所以prefix=[+,3,5,7]
- 由于3+5的结果可以和7算乘法,所以prefix=[*,+,3,5,7]
中缀转后缀
eg: (3+5)*7
我们按照如下步骤将其转换为后缀表达式:
由于后缀表达式要求运算符在操作数之后,所以必须从前向后扫描中缀表达式
定义suffix=[]
- 扫描到3,一个操作数什么也干不了,所以suffix=[3]
- 扫描到+,此时什么也干不了,先记住+号
- 扫描到5,5和3之间可以算加法,所以suffix=[3,5,+]
- 扫描到*,此时什么也干不了,记住*号
- 扫描到7,由于3和5的结果可以和7算乘法,所以suffix=[3,5,+,7,*]
利用栈实现中缀转前缀
定义两个栈,一个是运算符栈,一个是操作数栈。
从后向前扫描中缀表达式
- 如果是操作数,直接push到操作数栈
- 如果是右括号,例如:)]},直接push到运算符栈
- 如果是左括号,那么运算符栈中一定在对应的右括号直到栈顶元素之间包含着运算符,此时一直pop运算符栈(弹出的运算符放到操作数栈中),直到遇到对应的右括号为止,此时就可以消除这一对括号
- 如果是运算符,那么需要比较它和栈顶元素的优先级。如果栈顶元素的优先级大,那么说明此时形如1+2*3,此时栈顶元素是*,那么由于2和3之间可以算乘法,所以直接弹出栈顶元素,然后把+号入栈。这个操作一直执行到栈顶元素的优先级小于当前运算符的优先级。(需要注意的是如果栈顶元素是右括号,那么不能弹栈,因为右括号要等到对应的左括号才能弹栈)
- 重复上面的步骤,直到扫描到中缀表达式的第一个token
def infix_to_prefix(expression):
#eg ['(', '3', '+', '5', ')', '*', '7']
operator_stack=[]#运算符栈
operand_stack=[]#操作数栈
operator_priority={'+':0,'-':0,'*':1,'/':1}
expression=expression[:]
expression.reverse()#转前缀的过程是从右至左扫描
#['7', '*', ')', '5', '+', '3', '(']
for e in expression:
if e==')':
operator_stack.append(e)
elif e=='(':
#operator_stack中的')'直到栈顶元素要全部弹出来
temp=operator_stack.pop()
while temp!=')':
operand_stack.append(temp)
temp=operator_stack.pop()
elif e in operator_priority:
#此时e是运算符,需要比较栈顶元素的优先级
while len(operator_stack)!= 0 and operator_stack[-1]!=')' and operator_priority[e]<operator_priority[operator_stack[-1]]:
operand_stack.append(operator_stack.pop())
operator_stack.append(e)
else:
operand_stack.append(e)
while len(operator_stack)!=0:
operand_stack.append(operator_stack.pop())
operand_stack.reverse()
return operand_stack
利用栈实现中缀转后缀
定义两个栈,一个是运算符栈,一个是操作数栈。
从前向后扫描中缀表达式
- 如果是操作数,直接push到操作数栈
- 如果是左括号,例如:(,直接push到运算符栈
- 如果是右括号,那么运算符栈中一定在对应的左括号直到栈顶元素之间包含着运算符,此时一直pop运算符栈(弹出的运算符放到操作数栈中),直到遇到对应的左括号为止,此时就可以消除这一对括号
- 如果是运算符,那么需要比较它和栈顶元素的优先级。如果栈顶元素的优先级大,那么说明此时形如2*3+1,此时栈顶元素是*,那么由于2和3之间可以算乘法,所以直接弹出栈顶元素,然后把+号入栈。这个操作一直执行到栈顶元素的优先级小于当前运算符的优先级。(需要注意的是如果栈顶元素是左括号,那么不能弹栈,因为左括号要等到对应的右括号才能弹栈)
- 重复上面的步骤,直到扫描到中缀表达式的最后一个token
def infix_to_suffix(expression):
#eg ['(', '3', '+', '5', ')', '*', '7']
operator_stack=[]#运算符栈
operand_stack=[]#操作数栈
operator_priority={'+':0,'-':0,'*':1,'/':1}
expression=expression[:]
for e in expression:
if e=='(':
operator_stack.append(e)
elif e==')':
temp=operator_stack.pop()
while temp!='(':
operand_stack.append(temp)
temp=operator_stack.pop()
elif e in operator_priority:
while len(operator_stack)!=0 and operator_stack[-1]!='(' and operator_priority[e]<operator_priority[operator_stack[-1]]:
operand_stack.append(operator_stack.pop())
operator_stack.append(e)
else:
operand_stack.append(e)
while len(operator_stack)!=0:
operand_stack.append(operator_stack.pop())
return operand_stack
根据前缀表达式求值
思路很简单,从后向前扫描前缀表达式,遇到操作数进栈,遇到运算符就弹出两个元素计算,计算的结果再次push进栈中
def compute_prefix_expression(prefix_expression):
stack=[]
operators=['+','-','*','/']
prefix_expression=prefix_expression[:]
prefix_expression.reverse()
for e in prefix_expression:
if e not in operators:
stack.append(e)
else:
assert len(stack)>=2
operand_right=stack.pop()
operand_left=stack.pop()
res=eval(operand_left+e+operand_right)
stack.append(str(res))
assert len(stack)==1
return stack.pop()
根据后缀表达式求值
思路很简单,从前向后扫描后缀表达式,遇到操作数进栈,遇到运算符就弹出两个元素计算,计算的结果再次push进栈中
def compute_suffix_expression(suffix_expression):
stack=[]
operators=['+','-','*','/']
suffix_expression=suffix_expression[:]
for e in suffix_expression:
if e not in operators:
stack.append(e)
else:
assert len(stack)>=2
operand_right=stack.pop()
operand_left=stack.pop()
res=eval(operand_left+e+operand_right)
stack.append(str(res))
assert len(stack)==1
return stack.pop()