栈和队列
栈
1.定义
栈是限制在一端进行插入操作和删除操作的线性表(俗称堆栈),允许进行操作的一端称为**“栈顶”,另一固定端称为“栈底”,当栈中没有元素时称为“空栈”**。
2.特点
- 栈只能在一端进行数据操作
- 栈模型具有先进后出或者叫做后进先出的规律
3.栈的代码实现
*顺序存储代码实现: *
# 自定义异常
class StackError(Exception):
pass
# 顺序栈类
class SStack:
def __init__(self):
# 空列表就是栈的存储空间
# 列表的最后一个元素作为栈顶
self._elements = []
# 判断列表是否为空
def is_empty(self):
return self._elements == []
# 入栈
def push(self, value):
self._elements.append(value)
# 出栈
def pop(self):
if self.is_empty():
raise StackError("Stack is empty")
# 弹出并返回
return self._elements.pop()
# 查看栈顶元素
def top(self):
if self.is_empty():
raise StackError("Stack is empty")
return self._elements[-1]
if __name__ == "__main__":
st = SStack() # 初始化栈
print(st.is_empty())
st.push(7)
st.push(3)
st.push(16)
st.push(8)
while not st.is_empty():
print(st.pop())
思路总结:
1.列表即顺序存储﹐但功能多﹖不符合栈的模型特征
2.利用列表将其封装﹐提供接口方法,实现栈顺讯存储
*链式存储代码实现: *
# 自定义异常
class StackError(Exception):
pass
# 节点类
class Node:
def __init__(self, value, next_node=None):
self.value = value # 有用数据
self.next_node = next_node # 循环下一个节点关系
# 链式栈操作
class LStack:
def __init__(self):
# 标记栈的栈顶位置
self._top = None
# 判断栈是否为空
def is_empty(self):
return self._top is None
# 入栈
def push(self, value):
node = Node(value, self._top)
self._top = node
# 出栈
def pop(self):
if self.is_empty():
raise StackError("Stack is empty")
value = self._top.value
self._top = self._top.next_node
return value
# 栈顶
def top(self):
if self.is_empty():
raise StackError("Stack is empty")
return self._top.value
if __name__ == "__main__":
ls = LStack()
print(ls.is_empty())
ls.push(5)
ls.push(4)
ls.push(2)
print(ls.pop())
print(ls.pop())
思路总结:
1.源于链表结构
2.封装栈的操作方法 (入栈、出栈、栈空、栈顶元素)
3.链表的开头作为栈顶 ? (不用每次遍历)
练习1:入栈顺序为1,2,3,问出栈的顺序不可能是什么?
练习2:完成逆波兰表达式的实现
队列
1.定义
队列是限制在两端进行插入操作和删除操作的线性表,允许进行
存入操作的一端称为“队尾”,允许进行删除操作的一端称为**“队头**”。
2.特点
- 队列只能在队头和队尾进行数据操作
- 队列模型具有先进先出或者叫做后进后出的规律
3.队列的代码实现
队列的操作有入队,出队,判断队列的空满等操作。
*顺序存储代码实现: *
# 自定义队列异常
class QueueError(Exception):
pass
# 队列操作
class SQueue:
# 初始化
def __init__(self):
self._elements = []
# 判断队列是否为空
def is_empty(self):
return self._elements == []
# 入队,列表尾部定义为队尾
def enqueue(self, value):
self._elements.append(value)
# 出队
def dequeue(self):
if self.is_empty():
raise QueueError("Queue is empty")
return self._elements.pop(0)
if __name__ == "__main__":
sq = SQueue()
for i in range(100):
sq.enqueue(i)
"""将队列翻转"""
from sstack import *
st = SStack()
# 循环出队入栈
while not sq.is_empty():
st.push(sq.dequeue())
# 循环出栈入队
while not st.is_empty():
sq.enqueue(st.pop())
while not sq.is_empty():
print(sq.dequeue())
*链式存储代码实现: *
# 自定义队列异常
class QueueError(Exception):
pass
# 节点类
class Node:
def __init__(self, value, next_node=None):
self.value = value
self.next_node = next_node
# 队列操作
class LQueue:
def __init__(self):
# 定义队头和队尾的属性变量
self.front = self.rear = Node(None)
self.head = self.front
# 判断队列是否为空
def is_empty(self):
return self.front is self.rear
# 入队 rear动
def enqueue(self, value):
self.rear.next_node = Node(value)
self.rear = self.rear.next_node
# 出队 front动
def dequeue(self):
if self.is_empty():
raise QueueError("Queue is empty")
self.front = self.front.next_node
return self.front.value
if __name__ == "__main__":
lq = LQueue()
print(lq.is_empty())
lq.enqueue(5)
lq.enqueue(7)
lq.enqueue(4)
while not lq.is_empty():
print(lq.dequeue())