【数据结构与算法Python版学习笔记】基本数据结构——栈 stack
定义
-
一个项的有序集合
-
添加项和移除项都发生在同一“端”
-
分为栈顶和栈底
-
LIFO 先进后出
举例
- 浏览器后退
- word undo
抽象数据类型
栈的操作如下:
-
Stack()
创建一个新的空栈。它不需要参数,并返回一个空栈。 -
Push(item)
将新项添加到堆栈的顶部。它需要参数 item 并且没有返回值。 -
pop()
从栈顶删除项目。它不需要参数,返回 item。栈被修改。 -
peek()
返回栈顶的项,不删除它。它不需要参数。堆栈不被修改。 -
isEmpty()
测试看栈是否为空。它不需要参数,返回一个布尔值。 -
size()
返回栈的项目数。它不需要参数,返回一个整数。
#实现stack
class Stack:
def __init__(self):
self.items = []
def isEmpty(self):
return self.items == []
def push(self, item): # 将item加入栈顶,无返回值
return self.items.append(item)
def pop(self): # 将栈顶数据项移除,并返回,栈被修改
return self.items.pop()
def peek(self): # "窥视"栈顶数据项,返回栈顶的数但不移除,栈不被修改
return self.items[len(self.items)-1]
def size(self):
return len(self.items)
s=Stack()#创建一个空栈,不包含任何数据项
print(s.isEmpty())
s.push(4)
s.push('dog')
print(s.peek())
print(s.size())
应用
简单括号匹配
- 简单括号匹配
()
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 += 1
if balanced and s.isEmpty():
return True
else:
return False
if __name__ == "__main__":
print(parChecker("((()))"))
print(parChecker("(()"))
print(parChecker("(()())"))
print(parChecker("(()()"))
- 通用括号匹配
{[()]}
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 martches(top,symbol):
balanced = False
index += 1
if balanced and s.isEmpty():
return True
else:
return False
def martches(open,close):
opens="([{"
closers=")]}"
return opens.index(open)==closers.index(close)
if __name__ == "__main__":
print(parChecker("{{([][])}()}"))
print(parChecker("[{()]"))
进制转换
-
十进制转二进制
def divideBy2(decNumber): remstack=Stack() while decNumber>0: remstack.push(decNumber%2) decNumber//=2 binString="" while not remstack.isEmpty(): binString+=str(remstack.pop()) return binString if __name__ == "__main__": print(divideBy2(42))
-
十进制转十六进制以下任意进制
def baseConverter(decNumber,base): digits="0123456789ABCDEF" remstack=Stack() while decNumber>0: remstack.push(decNumber%base) decNumber//=base binString="" while not remstack.isEmpty(): binString+=digits[remstack.pop()] return binString if __name__ == "__main__": print(baseConverter(42,16)) print(baseConverter(255,16))
表达式转换
-
中辍表达式
- 优先级
- 全括号中辍表达式
-
前缀表达式
-
后缀表达式
通用中缀转后缀算法
-
步骤
- 创建空栈opstack用于暂存操作符,空表postfixList用于保存后缀表达式
- 将中缀表达式转换为单词(token)列表
- 从左到右扫描中缀表达式单词列表
- 若单词是操作符,则直接添加到后辍表达式列表末尾
- 若单词是“(”,则压入opstack栈顶
- 若单词是“)”,则反复弹出opstack栈顶操作符,加入到输出列表末尾,直到碰到左括号
- 若单词是操作符“*/+-”,则压入opstack栈顶
- 压入前要比较其与栈顶操作符的优先级
- 如果栈顶比较高,则反复弹出栈顶操作符,加入到输出列表末尾
- 知道栈顶操作符优先级低于它
- 扫描结束后,把opstack栈中的所有剩余操作符一次弹出,添加到输出列表末尾
- 把输出列表用join方法合并成后缀表达式字符串,算法结束
-
示例图
-
代码
def infixToPostfix(infixexpr):
prec={}
prec["*"]=3
prec["/"]=3
prec["+"]=2
prec["-"]=2
prec["("]=1
opStack=Stack()
postfixList=[]
tokenList=infixexpr.split()
#return tokenList
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)
if __name__ == "__main__":
print(infixToPostfix("( A * B ) + ( C * D )"))
print(infixToPostfix("( ( A + B ) * ( C + D ) )"))
print(infixToPostfix("( A + B * C + D )"))
后缀表达式求值
- 步骤
- 创建空栈operandStack用于暂存操作数
- 将后缀表达式用split方法解析为单词(token)的列表
- 从左到右扫描单词列表
- 若单词是一个操作数,将单词转换为整数int,压入operandStack栈顶
- 若单词是一个操作符(*/+-),就开始求职,从栈顶弹出2个操作数,先弹出的是右操作数,后弹出的是左操作数,计算后将值重新压入栈顶
- 单词列表扫描结束后,表达式的值就在栈顶
- 弹出栈顶的值,返回
- 代码
def postfixEval(postfixExpr):
operandStack=Stack()
tokenList=postfixExpr.split()
print(tokenList)
for token in tokenList:
if token in "0123456789":
operandStack.push(int(token))
else:
operand1=operandStack.pop()
operand2=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
elif op=="-":
return op1-op2
if __name__ == "__main__":
print(postfixEval("7 8 + 9 1 + *"))
- 改进
import operator
def postfixEval(postfixExpr):
operandStack=Stack()
tokenList=postfixExpr.split()
print(tokenList)
operators={
'*':operator.mul,
'/':operator.truediv,
'+':operator.add,
'-':operator.sub,
}
for token in tokenList:
if token in "0123456789":
operandStack.push(int(token))
else:
operand1=operandStack.pop()
operand2=operandStack.pop()
result =operators[token](operand1,operand2)
operandStack.push(result)
return operandStack.pop()
if __name__ == "__main__":
print(postfixEval("7 8 + 9 1 + *"))
作者:砥才人
出处:https://www.cnblogs.com/shiroe
本系列文章为笔者整理原创,只发表在博客园上,欢迎分享本文链接,如需转载,请注明出处!