概述
1. 栈是保证元素后进先出(Last In First On,LIFO)
2. 队列是保证元素先进先出(First In First On, FIFO)
3. 应用环境:
计算过程分为一些顺序进行的步骤(任何复杂一点的计算都是这样)
计算中执行的某些步骤会不断产生一些后面可能需要的中间数据
产生的数据中有些不能立即使用,但有需要在将来使用
需要保存的数据的项数不能事先确定
栈:概念和实现
1. 栈(Stack)是一种容器,可存入数据元素、访问元素、删除元素等。
2. 栈的抽象数据类型
ADT Stack:
Stack(self) #创建空栈
is_empty(self) #判断栈是否为空,空时返回Ture否则返回False
push(self,elem) #将元素elem加入栈,也常称为压入或推入
pop(self) #删除栈内最后压入的元素并将其返回,常称为弹出
top(self) #取得栈里最后压入的元素,不删除
3.栈的顺序表实现,后端插入和删除是O(1)操作,对于链接表,前端插入和删除都是O(1)操作。
'''栈的顺序表实现'''
class StackUnderflow(ValueError):
pass
class SStack():
def __init__(self):
self._elem = []
def is_empty(self):
return self._elem == []
def top(self):
if self._elem == []:
raise StackUnderflow("in SStack.top()")
return self._elem[-1]
def push(self, elem):
self._elems.append(elem)
def pop(self):
if self._elems == []:
raise StackUnderflow("in SStack.top()")
return self._elems.pop()
'''栈的链接表实现'''
class StackUnderflow(ValueError):
pass
class LStack():
def __init__(self):
self._top = None
def is_empty(self):
return self_top is None
def top(self):
if self._top is None:
raise StackUnderflow("in LStack.top()")
return self._top.elem
def push(self, elem):
self._top = LNode(elem, self._top)
def pop(self):
if self._top is None]:
raise StackUnderflow("in LStack.top()")
p = self._top
self._top = p.next
return p.elem
2. 表达式的表示、计算和变换
中缀形式:(3 - 5) * (6 + 17 * 4)/ 3
前缀形式:/ * - 3 5 + 6 * 17 4 3
后缀形式:3 5 - 6 17 4 * + * 3 /
3. 简单背包问题
''' 括号匹配文图'''
parens = "()[]{}"
open_parens = "([{"
opposite = {
")": "(", "[": "]", "}": "{"
}
def check_parens(text):
parens = "()[]{}"
open_parens = "([{"
opposite = {
")": "(", "[": "]", "}": "{"
}
def parentheses(text):
i, text_len = 0, len(text)
while True:
while i < text_len and text[i] not in parens:
i += 1
if i >= text_len:
return
yield text[i], i
i += 1
st = SStack()
for pr, i in parentheses(text):
if pr in open_parens:
st.push(pr)
elif st.pop() != opposite[pr]:
print("Unmatching is found at", i, "for", pr)
return False
print("All parentheses are correctly matched.")
return True
'''后缀表达式'''
def suffix_exp_evaluator(line):
return suffix_exp_evaluator(line.split())
class ESStack(SStack):
def depth(self):
return len(self._elems)
def suf_exp_evaluator(exp):
operators = "+-*/"
st = ESStack()
for x in exp:
if x not in operators:
st.push(float(x))
continue
if st.depth() < 2:
raise SyntaxError("Short of operand(s).")
a = st.pop()
b = st.pop()
if x == "+":
c = b + a
elif x == "-":
c = b - a
elif x == "*":
c = b * a
elif x == "/":
c = b / a
else:
break
st.push(c)
if st.depth():
return st.pop()
raise SyntaxError("Extra operand(s).")
ADT Queue:
Queue(self) #创建空队列
is_empty(self) #判断队列是否为空
enqueue(self, elem) #将元素elem加入队列,常称为入队
dequeue(self) #删除队列里最早进入的元素并将其返回,常称为出队
peek(self) #查看队列里最早进入的元素,不删除
队列类的实现
class SQueue():
def __init__(self, init_len=8):
self._len = init_len
self._elems = [0] * init_len
self._head = 0
self._num = 0
def is_empty(self):
return self._num
def peek(self):
if self._num = 0:
raise QueueUnderflow
return self._elems[self._head]
def dequeue(self):
if self._num == 0:
raise QueueUnderflow
e = self._elems[self._head]
self._head = (self._head+1) % self._len
self._num -= 1
return e
def enqueue(self, e):
if self._num == self._len:
self.__extend()
self._elems[(self._head+self._num) % self._len] = e
self._num += 1
def __extend(self):
old_len = self._len
self._len *= 2
new_elems = [0]*self._len
for i in range(old_len):
new_elems[i] = self._elems[(self._head+i) % old_len]
self._elems, self._head = new_elems, 0
'pos为二元序对(i, j)普通方法'
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
def mark(maze, pos): #给迷宫maze的位置pos标2表示“到过了”
maze[pos[0]][pos[1]] = 2
def passable(maze, pos): #检查迷宫maze的位置pos时候可行
return maze[pos[0]][pos[1]] == 0
def find_path(maze, pos, end):
mark(maze, pos)
if pos == end: #已到达出口
print(pos, end=" ") #输出这个位置
return True #成功结束
for i in range(4): #否则按四个方向顺序探查
nextp = pos[0] + dirs[i][0], pos[1] + dirs[i][1]
#考虑下一个可能方向
if passable(maze, nextp):
if find_path(maze, nextp, end):
print(pos, end=" ") # 输出这个位置
return True
return False
'''堆栈实现'''
class StackUnderflow(ValueError):
pass
dirs = [(0, 1), (1, 0), (0, -1), (-1, 0)]
def mark(maze, pos): #给迷宫maze的位置pos标2表示“到过了”
maze[pos[0]][pos[1]] = 2
def passable(maze, pos): #检查迷宫maze的位置pos时候可行
return maze[pos[0]][pos[1]] == 0
class SStack():
def __init__(self):
self._elem = []
def is_empty(self):
return self._elem == []
def top(self):
if self._elem == []:
raise StackUnderflow("in SStack.top()")
return self._elem[-1]
def push(self, elem):
self._elems.append(elem)
def pop(self):
if self._elems == []:
raise StackUnderflow("in SStack.top()")
return self._elems.pop()
def maze_solver(maze, start, end):
if start == end:
print(start)
return
st = SStack()
mark(maze, start)
st.push((start, 0))
while not st.is_empty():
pos, nxt = st.pop()
for i in range(nxt, 4):
nextp = (pos[0] + dirs[i][0],
pos[1] + dirs[i][1])
if nextp == end:
print("maze end")
return
if passable(maze, nextp):
st.push((pos, i+1))
mark(maze, nextp)
st.push((nextp, 0))
break
print("No path found.")