定义
栈
栈实现数据的后进先出(LIFO)
这边用列表的方式构造栈
ps:python3版本默认加载了object了(即使没有写上object),所以python3版本在写类的时候加不加object没有区别。
class Stack:
"""栈"""
def __init__(self):
self.items = []
def is_empty(self):
"""判断是否为空"""
return self.items == []
def push(self, item):
"""加入元素"""
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)
if __name__ == "__main__":
stack = Stack()
stack.push("hello")
stack.push("world")
stack.push("itcast")
print stack.size()
print stack.peek()
print stack.pop()
print stack.pop()
print stack.pop()
-
pop()方法用于删除列表中的最后一个元素,并返回该元素本身
-
也可通过下标(从0开始)指定删除某个元素
a=[1,2,3,4,5]
a.pop() # 5
a # [1,2,3,4]
- pop()只有一个参数位
队列
class Queue(object):
"""队列"""
def __init__(self):
self.items = []
def is_empty(self):
return self.items == []
def enqueue(self, item):
"""进队列"""
self.items.insert(0,item)
def dequeue(self):
"""出队列"""
return self.items.pop()
def size(self):
"""返回大小"""
return len(self.items)
if __name__ == "__main__":
q = Queue()
q.enqueue("hello")
q.enqueue("world")
q.enqueue("itcast")
print q.size()
print q.dequeue()
print q.dequeue()
print q.dequeue()
- list. insert(index, obj)。其中index 是对象 obj 需要插入的索引位置,obj是要插入列表中的对象。
vowel = ['a', 'e', 'i', 'u']
vowel.insert(3, 'o')
print('更新列表: ', vowel)
# 更新列表: ['a', 'e', 'i', 'o', 'u']
其中insert索引的位置如下

232. 用栈实现队列
思路
首先想到的是,比较形象地描述:队列是“双开口”的,栈是“单开口”的。如果想要用栈实现队列自然需要两个栈。
而如何将两个栈“连”起来,则比较麻烦。下面画了简单的原理图:
利用python里面常用的.append()和.pop()函数可以实现“入栈”和“出栈”的操作。
Ps:关键是要有栈的一些限制,必须是“后进先出”。不能用一些函数直接把最开始的数取出来了。
代码
class MyQueue:
def __init__(self):
"""
in用于push,out用于破pop
"""
self.stack_in = []
self.stack_out = []
def push(self, x: int) -> None:
self.stack_in.append(x)
def pop(self) -> int:
if self.empty(): # 两个栈为空则不再输出
return None
if self.stack_out:
return self.stack_out.pop()
else:
while len(self.stack_in)>0:
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
def peek(self) -> int:
ans = self.pop()
self.stack_out.append(ans)
return ans
def empty(self) -> bool:
return not (self.stack_in or self.stack_out)
# Your MyQueue object will be instantiated and called as such:
# obj = MyQueue()
# obj.push(x)
# param_2 = obj.pop()
# param_3 = obj.peek()
# param_4 = obj.empty()
反思
1、pop为什么要考虑stack_out是否为空?
def pop(self) -> int:
if self.empty(): # 两个栈为空则不再输出
return None
if self.stack_out:
return self.stack_out.pop()
else
while len(self.stack_in)>0:
self.stack_out.append(self.stack_in.pop())
return self.stack_out.pop()
当stack_out为空时,会将stack_in的所有元素放进stack_out才能获得队头元素,但取出队头元素后, stack_out中还会有剩余的元素。下次取队头元素,只需要从stack_out中pop()就可以。
2.peek为什么需要把元素取出来再放进stack_out?
def peek(self) -> int:
ans = self.pop()
self.stack_out.append(ans)
return ans
考虑到上面取出时的三种情况,因此直接用pop取出队头元素,会避免很多麻烦。
3.如何写empty函数比较简洁?
一开始我自己写的如下
def empty(self) -> bool:
if len(self.stack_in)+len(self.stack_out)==0:
return True
else:
return False
后来看了答案,发现答案写的更简洁
def empty(self) -> bool:
return not (self.stack_in or self.stack_out)
数组也是可以用or来判断是否为空的。
两个数组只要有一个不是空的则返回False。
知识点回顾
1、python删除函数回顾
- remove()
- pop()
- del()
- remove()函数
remove() 函数可以删除列表中的指定元素,且一次只能删除一个元素。
a=[1,2,3,2]
a.remove(2)
print(a)
#输出:[1,3,2]
- pop()函数
pop() 函数用于随机移除列表中的一个元素(默认最后一个元素),并且返回该元素的值。
fruits = {'apple','banana','cherry'}
x = fruits.pop()
print(x)
print(fruits)
#输出:
#banana
#{'cherry', 'apple'}
pop()也可用于删除指定下标的数组元素(下标从0开始)
a=[1,2,3,2]
x=a.pop(1)
print(x)
print(a)
#输出:
#2
#[1,3,2]
- del()函数
del删除的是变量,而不是数据
li=[1,2,3,4,5] #列表本身不包含数据1,2,3,4,5,而是包含变量:li[0] li[1] li[2] li[3] li[4]
first=li[0] #拷贝列表,也不会有数据对象的复制,而是创建新的变量引用
del li[0]
print(li) #输出[2, 3, 4, 5]
print(first) #输出 1
225. 用队列实现栈
题目链接:225. 用队列实现栈
用两个队列que1和que2实现队列的功能,que2其实完全就是一个备份的作用
一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
思路一
用两个队列,队列1用来存储,队列2用来pop。
当需要pop时, 用将队列1前n-1个元素放入队列2,此时队列1只剩下一个栈顶元素。然后交换队列1和队列2,从队列2取出元素,即为栈顶元素
代码一
class MyStack:
def __init__(self):
self.queue_in=deque() # 存数据使用
self.queue_out=deque() # 仅在pop时使用
def push(self, x: int) -> None:
self.queue_in.append(x)
def pop(self) -> int:
if self.empty():
return None
for i in range(len(self.queue_in)-1):
self.queue_out.append(self.queue_in.popleft())
self.queue_in, self.queue_out = self.queue_out, self.queue_in #所以说out只是用来存储的
return self.queue_out.popleft()
def top(self) -> int:
ans = self.pop()
self.queue_in.append(ans)
return ans
def empty(self) -> bool:
return len(self.queue_in)==0
思路二
只用一个队列。一个队列在模拟栈弹出元素的时候只要将队列头部的元素(除了最后一个元素外) 重新添加到队列尾部,此时再去弹出元素就是栈的顺序了。
class MyStack:
def __init__(self):
self.queue=deque()
def push(self, x: int) -> None:
self.queue.append(x)
def pop(self) -> int:
if self.empty():
return None
for i in range(len(self.queue)-1):
self.queue.append(self.queue.popleft())
return self.queue.popleft()
def top(self) -> int:
ans = self.pop()
self.queue.append(ans)
return ans
def empty(self) -> bool:
return len(self.queue)==0
知识点回顾
1、collections模块中的deque双端队列结构
deque 是 double-ended queue的缩写,类似于 list,不过提供了在两端插入和删除的操作。
- appendleft 在列表左侧插入
- popleft 弹出列表左侧的值
- extendleft 在左侧扩展
#-*- coding: UTF-8 -*-
from collections import deque
# mydeque =deque() 创建一个普通队列
# 可以指定 队列的长度
mydeque=deque(maxlen=10)
print(mydeque.maxlen) # 10
# 默认从右边加入
mydeque.append(10)
mydeque.append(12)
print(mydeque) # deque([10, 12])
# 也可以从左边加入
mydeque.appendleft('a')
mydeque.appendleft('b')
print(mydeque) # deque(['b', 'a', 10, 12])
mylist= range(5,7)
# 也可以加入一个列表,默认从右边加入
# mydeque.extend(mylist)
mydeque.extendleft(mylist) # 从左边扩展
print(mydeque) # deque([6, 5,'b', 'a', 10, 12])
# 出队列,返回出队列的元素
# 可以从左边也可以从右边 出队列
mydeque.pop() # 12
mydeque.popleft() # 6
# 查看 队列里面元素个数
print(len(mydeque)) # 4
# 统计元素的个数
#统计a 有几个
print(mydeque.count('a')) # 1
# 在某个位置insert 一个元素
# insert(i, x)
# Insert x into the deque at position i.
mydeque.insert(3,'frank')
print(mydeque) # deque([6, 5,'b', 'frank','a', 10, 12])
#翻转操作
mydeque.reverse()
print(mydeque) # deque([12,10,'a','frank','b',5,6])
# remove 移除某个元素
mydeque.remove('frank')
print(mydeque) # deque([12,10,'a','b',5,6])
# 清空队列元素 clear
mydeque.clear()
print(mydeque) # deque([])
rotate 方法:
value 是步长,rotate(value) 对队列实行旋转操作(每个元素依次向后移动value步,最后一个移动到第一个算一步)
from collections import deque
d = deque()
d.extend(['a', 'b', 'c', 'd', 'e'])
d.rotate(2) # 指定次数,默认1次
print(d) # deque(['d', 'e', 'a', 'b', 'c'])
maxlen 说明
- 如果构建deque 的时候,指定了maxlen, 则可以通过 d.maxlen 来获得dueue的最大长度.
- 如果插入的数据大于 maxlen 则会自动删除旧的元素.
- 删除 什么元素,取决于, 从哪边添加数据.
d = deque(list(range(5)),maxlen=5)
d
Out[21]: deque([0, 1, 2, 3, 4])
d.maxlen
Out[26]: 5
# 从左边添加元素, # 元素4 被挤出 队列
d.appendleft('frank')
d
Out[23]: deque(['frank', 0, 1, 2, 3])
# 从右边添加元素, 元素 'frank' 被挤出队列.
d
Out[23]: deque(['frank', 0, 1, 2, 3])
d.append('xiaoming')
d
Out[25]: deque([0, 1, 2, 3, 'xiaoming'])