栈,队列,deques, 列表是一类容器,他们数据项之间的顺序由添加或删除的顺序决定,一旦一个数据项被添加,它相对于前后元素一直保持该位置不变。注入此类的数据结构称为线性数据结构。
栈
栈(栈,队列,deques, 列表)是一个项的有序集合:栈的底部很重要,因为在栈中靠近底部的项是存储时间最长的。最近添加的项是最先会被移除的。这种排序原则有时被称为 LIFO,后进先出。
1.栈的抽象数据类型
栈被构造为项的有序集合,其中项被添加和从末端一处的位置称为顶部,栈是有序的LIFO。栈操作如下:
- Stack()创建一个空的新栈。它不需要参数,并返回一个空栈。
- push(item)将一个新项添加到栈的顶部。它需要item做参数并不返回任何内容。
- pop()从栈中删除顶部项。它不需要参数并返回item。栈被修改。
- peek()从栈返回顶部项,但不会删除它。不需要参数,不修改栈。
- isEmpty()测试栈是否为空。不需要参数,并返回boolean值。
- size()返回栈中的item数量。不需要参数,并返回一个整数。
2.python实现栈
#栈
class Stack(object):
def __init__(self, ):
self.items = list()
def isEmpty(self):
return self.items == []
def size(self):
return len(self.items)
def push(self, item):
self.items.append( item)
def pop(self):
return self.items.pop()
def peek(self):
return self.items[-1]
3.实例应用
3.1括号匹配
# 判断括号匹配
def parChecker(symbolString):
s = Stack()
balance = True
index = 0
while index < len(symbolString) and balance:
symbol = symbolString[index]
if symbol in '([{':
s.push(symbol)
else:
if s.isEmpty():
balance = False
break
else:
top = s.pop()
if not matches(top, symbol):
balance = False
index += 1
if balance and s.isEmpty():
return True
else:
return False
def matches(open,close):
opens = "([{"
closers = ")]}"
return opens.index(open) == closers.index(close)
print(parChecker('[(()){}]'))
print(parChecker(''))
print(parChecker('()()))'))
print(parChecker('[{}]('))
3.2十进制转二进制
#十进制转二进制
def dec2bin(num):
s = Stack()
while num > 0:
r = num % 2
s.push(r)
num //= 2
binstring = ''
while not s.isEmpty():
binstring = binstring + str(s.pop())
return binstring
dec2bin(233)
3.3中缀前缀和后缀表达式
中缀转换为后缀的算法:
首先假设中缀表达式是一个由空格分隔的标记字符串。 操作符标记是*,/,+
和 -
,以及左右括号。操作数是单字符 A,B,C 等。 以下步骤将后缀顺序生成一个字符串。
- 创建一个名为 opstack 的空栈以保存运算符。给输出创建一个空列表。
- 通过使用字符串方法拆分将输入的中缀字符串转换为标记列表。
- 从左到右扫描标记列表。
- 如果标记是操作数,将其附加到输出列表的末尾。
- 如果标记是左括号,将其压到 opstack 上。
- 如果标记是右括号,则弹出 opstack,直到删除相应的左括号。将每个运算符附加到输出列表的末尾。
- 如果标记是运算符,
*,/,+
或-
,将其压入 opstack。但是,首先删除已经在 opstack 中具有更高或相等优先级的任何运算符,并将它们加到输出列表中。
- 当输入表达式被完全处理时,检查 opstack。仍然在栈上的任何运算符都可以删除并加到输出列表的末尾。
下图展示了对表达式 A * B + C * D
的转换算法。
#中缀表达式转换为后缀表达式
def infix2Posfix(exp):
prec = {}
prec['('] = 1
prec['+'] = 2
prec['-'] = 2
prec['*'] = 3
prec['/'] = 3
s = Stack()
postfixList = []
tokenList = exp.split()
print(tokenList)
for token in tokenList:
# print(token)
if token in "ABCDEFGHIJKLMNOPQRSTUVWXYZ" or token in "0123456789":
postfixList.append(token)
elif token == '(':
s.push(token)
elif token == ')':
top = s.pop()
while top != '(':
postfixList.append(top)
top = s.pop()
# s.pop()
else:
# top = s.peek()
while (not s.isEmpty() and prec[token] <= prec[s.peek()] ):
postfixList.append(s.pop())
# print(s.size())
s.push(token)
while not s.isEmpty():
postfixList.append(s.pop())
return ' '.join(postfixList)
s = 'A * B + C * D'
s1 = 'A + B * C + D'
s2 = '( A + B ) * ( C + D )'
print(infix2Posfix(s))
print(infix2Posfix(s1))
print(infix2Posfix(s2))
后缀表达式求值:
假设后缀表达式是一个由空格分隔的标记字符串。 运算符为*,/,+
和 -
,操作数假定为单个整数值。 输出将是一个整数结果。
- 创建一个名为
operandStack
的空栈。 - 拆分字符串转换为标记列表。
- 从左到右扫描标记列表。
- 如果标记是操作数,将其从字符串转换为整数,并将值压到operandStack。
- 如果标记是运算符
*,/,+
或-
,它将需要两个操作数。弹出operandStack 两次。 第一个弹出的是第二个操作数,第二个弹出的是第一个操作数。执行算术运算后,将结果压到操作数栈中。
- 当输入的表达式被完全处理后,结果就在栈上,弹出 operandStack 并返回值。
#后缀表达式求值 def postfixEval(postfixexp): s = Stack() postfixList = postfixexp.split() for token in postfixList: if token in '+-*/': op2 = s.pop() op1 = s.pop() val = doMath(token, int(op1), int(op2)) s.push(val) else: s.push(token) return s.pop() def doMath(op, op1, op2): if op == "*": return op1 * op2 elif op == "/": return op1 / op2 elif op == "+": return op1 + op2 else: return op1 - op2 print(postfixEval('7 8 + 3 2 + /'))
其他线性数据结构:
队列:https://blog.csdn.net/qq_18888869/article/details/88134592
列表(链表):https://blog.csdn.net/qq_18888869/article/details/88138785
deque:https://blog.csdn.net/qq_18888869/article/details/88137237
github代码:https://github.com/makang101/python-data-structure
参考:
problem-solving-with-algorithms-and-data-structure-using-python 中文版
数据结构(C语言版)严蔚敏