栈与队列
栈
栈的是一种线性结构,栈存储数据类似于乒乓球筒中放入或取出乒乓球的过程,遵从先进后出的原则。
栈相比于同样是线性结构的顺序表,关闭了部分接口,提高程序的稳定性。
用Python实现栈
- Stack()创建一个新的空栈
- push(item)添加一个新的元素item到栈顶
- pop()弹出栈顶元素
- peek()返回栈顶元素
- is_empty()判断栈是否为空
- size()返回栈的元素个数
- tracel()输出栈中所以元素
class Stack:
def __init__(self):
self.__data = []
def is_empty(self):
"""判断栈是否为空"""
return self.__data == []
def push(self, data):
"""在栈顶添加元素"""
self.__data.append(data)
def pop(self):
"""弹出顶部元素"""
return self.__data.pop()
def peek(self):
"""返回栈顶元素"""
# 先判断是否为空
if self.is_empty():
return
else:
return self.__data[-1]
def size(self):
"""判断长度"""
return len(self.__data)
def travel(self):
"""遍历所有元素"""
self.__data = self.__data[::-1]
for i in self.__data:
print(i)
if __name__ == '__main__':
a = Stack()
print(a.is_empty())
a.push(0)
a.push(1)
a.push(2)
a.push(3)
a.travel()
使用Python中的列表,我们可以轻松的创建一个栈,栈在程序中用处是较多的一种结构,我们浏览器的前进后推中就用到了栈
浏览器中用到的栈
当我们没次访问一个新页面,浏览器就会已栈的结构记下一条我们的浏览记录。之后如果我们需要返回,浏览器就会输出栈顶数据,也就是我们最后访问的那个页面。并同时将栈顶元素存档在另一个栈中,一共后续前进使用。
if __name__ == '__main__':
prev = Stack()
next = Stack()
i = 1
while True:
print('按1为点击新页面,2为返回,3为前进')
a = int(input('请输入数字: '))
if a == 1:
prev.push(f'第{i}个页面')
print(f'当前在{prev.peek()}')
i += 1
elif a == 2:
if prev.is_empty():
print('不存在上个页面')
elif prev.size() == 1:
print('首页无法返回')
else:
next.push(prev.pop())
print(f'当前在{prev.peek()}')
elif a == 3:
if next.is_empty():
print('不存在下个页面')
else:
prev.push(next.pop())
print(f'当前在{prev.peek()}')
队列
队列遵循的是后出原则,队列和栈都是受限制的线性表结构,队列相较于栈更好理解,因为平时我们都或多或少经历过排队。而且队列的使用也相当多,比如说并发队列,循环队列,阻塞队列,在系统底层、框架、中间件的开发中,起着关键性作用。
## 用Python实现队列
class Queue:
def __init__(self):
self.__data = []
def enqueue(self, data):
"""往队列头中添加一个新元素"""
self.__data.insert(0, data)
def travel(self):
"""遍历所有元素"""
for i in self.__data:
print(i, end='')
print('')
def dequeue(self):
"""从队列尾删除一个元素"""
self.__data.pop()
def is_empty(self):
"""判断队列是否为空"""
return self.__data == []
def size(self):
"""返回队列的元素个数"""
return len(self.__data)
队列和栈在代码是现实上非常相似,都可以算是一种受到限制的顺序表
双端队列
双端队列可在队列任意一侧出队入队。
双端队列只需加入对头的出队和队尾入队的方式即可
def appqueue(self, data):
"""在队尾添加新元素"""
self.__data.append(data)
def delqueue(self):
"""删除对头元素"""
self.__data.pop(0)
扩展
我们发现栈和队列中有大量相同的方法,我们可以使用继承和封装来优化代码
# 利用继承写栈与队列
class Repeat:
def __init__(self):
self.__data = []
def is_empty(self):
"""判断是否为空"""
return self.__data == []
def push(self, data):
"""头部添加元素"""
self.__data.insert(0, data)
def travel(self):
"""遍历所有元素"""
for i in self.__data:
print(i)
print('')
def size(self):
"""返回队列的元素个数"""
return len(self.__data)
@property
def data(self):
return self.__data
@data.setter
def data(self, n):
self.__data = n
class Stack(Repeat):
def pop(self):
"""弹出顶部元素"""
return self.data.pop(0)
def peek(self):
"""返回栈顶元素"""
# 先判断是否为空
if self.is_empty():
return False
else:
return self.data[0]
class Queue(Repeat):
def pop(self):
"""队尾元素出队"""
return self.data.pop()