【漫漫长征路D3】数据结构 #栈
本文为我在 中国大学mooc 数据结构与算法Python版的学习笔记
栈 Stack
后进先出(LIFO)
抽象数据类型“栈”是一个有次序的数据集,每个数据项仅从“栈顶”一端加入到数据集中,从数据集中移除。
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)
简单括号匹配 // 更多种括号的匹配
次序反转: 第一个左括号就应该匹配最后一个右括号
balance and isEmpty()
碰到各种左括号依旧入栈
碰到右括号的时候需要判断栈顶的左括号是否为同一种类
if symbol in "{[(":
balabala
if not matches(top, symbol):
balabala
def matches(opener, closer):
opens = "{[("
closes = "}])"
return opens.index(opener) == closes.index(closer)
表达式转换
中缀表达式转换为前缀和后缀表达式
1)将中缀表达式转换为全括号形式
2)将所有的操作符移动到子表达式所在的左括号(前缀)或者右括号(后缀)处,替代之,再删除所有的括号。
(A + B) * C - (D - E) * (F + G)
(((A + B) * C) - ((D - E) * (F + G)))
Prefix: - * + A B C * - D E + F G
Postfix:A B + C * D E - F G + * -
从左到右扫描中缀表达式单词列表
……如果单词是操作数,则直接添加到后缀表达式列表的末尾
……如果单词是左括号“(”,则压入opstack栈顶
……如果单词是右括号“)”,则反复弹出opstack栈顶操作符,加入到输出列表末尾,直到碰到左括号
……如果单词是操作符“* / + - ”,则压入opstack栈顶
…………如果栈顶的操作符高于或等于它,就要反复弹出栈顶操作符,加入到输出列表末尾,直到栈顶的操作符优先级低于它
……中缀表达式单词列表扫描结束后,把opstack栈中的所有剩余操作符依次弹出,添加到输出列表末尾
……把输出列表用join方法合成后缀表达式字符串
def InfixToPostfix(infixx):
prec = {}
prec["*"] = 3
prec["/"] = 3
prec["+"] = 2
prec["-"] = 2
prec["("] = 1
opstack = Stack()
Postfix = []
infix = infixx.split()
for i in infix:
if i not in prec and i != ")":
Postfix.append(i)
elif prec[i] == 1:
opstack.push(i)
elif i == ")":
c = opstack.peek()
while( c != "("):
Postfix.append(opstack.pop())
opstack.pop()
else:
while(not opstack.isEmpty() and prec[opstack.peek()] >= prec[i]): # in case opstack is Empty
Postfix.append(opstack.pop())
opstack.push(i)
while not opstack.isEmpty():
Postfix.append(opstack.pop())
print(Postfix)
return " ".join(Postfix) #use join() to build a string
后缀表达式求值
操作符只作用于离他最近的两个操作数
暂存操作数,在碰到操作符的时候,再将暂存的两个操作数进行实际计算,结果压回栈中
。。需要注意:先弹出的是右操作数,后弹出的是左操作数
创建空栈operandstack用于暂存操作数
将后缀表达式用split方法解析为单词的列表
从左到右扫描单词列表如果单词是一个操作数,将单词转换为int,压入operandstack栈顶
如果单词是一个操作符,就开始求值,从栈顶弹出2个操作数,计算后将值重新压入栈顶单词列表扫描结束后,表达式的值就在栈顶
弹出栈顶的值,返回
def postfixEval(Postfix):
operandStack = Stack()
postfixEval = Postfix.split()
for i in postfixEval:
if i not in "+-*/":
operandStack.push(int(i))
else:
righ = operandStack.pop()
lef = operandStack.pop()
res = doMath(i, lef, righ)
operandStack.push(res)
return operandStack.pop()
def doMath(op, lef, righ):
if op =="*":
return lef * righ
elif op == "/":
return lef / righ
elif op == "+":
return lef + righ
else:
return lef - righ