一、栈的介绍
一种有次序的数据项的集合,在栈中,数据项的加入和移除都进发生在同一端。
特点:后进先出:反转次序
应用:① 浏览器后退按钮
② Word的“撤销”按钮
二、用Python实现Stack
我们可以将 Python List 的任意一端(index=0或者index=-1)设置为栈顶。这里我们选用List的末端(index=-1)作为栈顶这样栈的操作就可以通过对 list 的 append 和 pop 来实现。
# 用list模拟栈的判空、添加、获取栈顶元素、删除、获取栈的长度操作
class Stack():
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self,item):
self.items.append(item)
def peek(self):
return self.items[len(self.items)-1]
def pop(self):
return self.items.pop()
def size(self):
return len(self.items)
opt = Stack()
opt.push("hello")
print(opt.size()) # output:1
opt.push("cool")
print(opt.peek()) # output:cool
print(opt.isEmpty()) # output:False
三、栈的应用
在前缀和后缀表达式中,操作符的次序完全决定了运算的次序,不再有混淆。所以在很多情况下,表达式的计算机表示都避免用复杂的中缀形式。
1、中缀表达式转后缀表达式
# 记录操作符优先级
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 == ")":
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("( 1 + 2 ) * 3 + 8 / 2"))
# 输出 "1 2 + 3 * 8 2 / +"
2、后缀表达式求值
步骤:①生成一个栈,把输出字符串转换为列表;
②循环列表元素:如果元素是操作数就压入栈顶;
③循环列表元素:如果是操作数则弹出距离栈顶最近的两个元素,先弹出的是右操作数,后弹出的是左操作数,将计算的结果压入栈顶;
④单词列表扫面结束后,栈顶的值就是表达式的值。弹出栈顶的值,返回。
'''后缀表达式求值'''
def postfixEval(postfixExpr):
operandStack = Stack()
tokenList = postfixExpr.split()
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
if op == "/":
return op1 / op2
if op == "+":
return op1 + op2
if op == "-":
return op1 - op2
print(postfixEval("1 2 + 3 * 8 2 / +"))
输出:13.0
四、思考
题目:有一排商品,每一个商品都有自己的价值,现在需要花一定金额购买这些商品。规则是:如果一个商品的价值比它旁边的一个商品要高,那么这个商品就必须比它旁边的商品花费更多金额。所有的商品至少要进行一次金额购买。假设一次购买花费金额单位为1,最少需要多少金额可以购买所有商品?(题目来自牛客,思考是否能用栈实现)
输入案例:
1 4 2 1
输出:
7
参考资料:
学习《数据结构与算法(Python版)》课程笔记。
课程链接:【北京大学】数据结构与算法Python版(完整版).