说在前面——摆烂人的觉醒
假期没好好学,现在开始救赎自己,争取300元子不白给了(大哭)(已经白给了)
从现在开始我根据视频课来总结知识点(纯干货),并且做题练手!大家一起加油!!
文章目录
前言
我先从基础数据结构开始,前面的基础操作先略过,我最后填坑
这一章是基础数据结构,主要内容有数组,链表,队列和栈 还有 二叉树
这一篇主要讲解队列和栈(链表的话看上一篇)
以及一些相关习题
一、队列和栈是什么
队列是什么?
队列,就像他的名字一样,先到先得,先来的同学先打饭
特点:先进先出
1)只能从队头离开队列
2)只能从队尾进入队列
缺点:队列查找慢,从头到尾一个一个查找
其他好玩的:循环队列
栈是什么?
栈,就像一口井一样,后来居上,只有落井下石
特点:先进后出
只有唯一的一个出入口,既可进入又可出来,这是和队列的最大区别
二、队列的实现
队列的实现主要有三种:
1)用queue实现队列操作,有q.size()、q.empty()、q.put()、q.get()等功能
2)列表list就是一个普通队列 ( list复习参见上一篇)
3)collections.deque.deque最快,快30倍
0.一个例题
通过例题具体情景来加深对队列的理解
1.用queue实现队列
Queue模块是提供队列操作的模块
queue相关函数可以参见这里
from queue import* # 引入queue库
q = Queue() # 创建一个可操作的队列
n = eval(input()) # 实现n步操作
for i in range(n): # for循环,n次操作
s = list(map(int,input().split()))
if s[0] == 1: # 当指令为1时
q.put(s[1]) # 执行放入操作
elif s[0] == 2: # 当指令为2时
if not q.empty():
a = q.get() # 出队并打印
print(a)
else:
print('no') # 要不然打印no
break
elif s[0] == 3: # 当指令为3时
print(q.qsize()) # 统计队列元素个数
2.用list实现队列
用list实现一切已经是传统艺能了
list复习可以参考这个
n = eval(input()) # 操作数
q = [] # 创建一个栈
for i in range(n): # 循环操作
s = list(map(int,input().split()))
if s[0] == 1: # 操作为1
q.append(s[1]) # 在末尾添加
elif s[0] == 2: # 操作为1
if len(q) > 0:
q.reverse() # 很巧妙,先把数组翻转,再pop弹出,再翻转
a = q.pop() # 实现了删除开头的功能
print(a)
q.reverse()
else:
print('no')
break
elif s[0] == 3: # 操作为1
print(len(q)) # 数组长度
3.用deque实现队列
deque(双端队列)和 queue(队列)分别是Python标准库collections和queue模块中提供的数据结构,它们都用于存储元素集合,但是有一些关键的区别:
1. deque(双端队列):
- deque是collections模块中的一个类,它提供了一个两端都可以快速添加(append)和移除(popleft或popright)元素的数据结构。
- deque是为了在两端都提供O(1)时间复杂度的操作而设计的,这使得它在需要频繁在两端添加或移除元素的场景中非常高效。
- deque没有线程安全的功能,如果需要在多线程环境中使用,需要额外的同步机制。
2. queue(队列):
- queue是queue模块中的一个类,它提供了线程安全的队列实现,用于多线程编程中。
- queue实现了标准的FIFO(先进先出)队列,还提供了put方法用于将元素放入队列,`get`方法用于从队列中取出元素。
- queue模块还提供了其他类型的队列,如LifoQueue(后进先出队列,类似于栈)和PriorityQueue(优先级队列)。
- queue是设计用于多线程环境中的,它内部实现了必要的锁机制来保证线程安全。
总结来说,deque是一个高效的双端队列,适用于需要在两端进行快速操作的场合,而queue模块提供的是线程安全的队列实现,适用于多线程间的通信。选择哪一个取决于你的具体应用场景和需求。
from collections import* # 引入queue库
n = eval(input()) # 实现n步操作
q = deque() # 创建一个可操作的队列
for i in range(n): # for循环,n次操作
s = list(map(int,input().split()))
if s[0] == 1: # 指令为1时
q.append(s[1]) # 进入队列
elif s[0] == 2: # 指令为2时
if len(q)>0:
a = q.popleft() # 左端出队并打印
print(a)
else:
print('no') # 要不然打印no
break
elif s[0] == 3: # 指令为3时
print(len(q)) # 统计队列元素个数
4.Python优先队列
一个蛮不讲理的队列——PriorityQueue
PriorityQueue是 Python 标准库 queue 模块中的一个类,它实现了具有优先级排序的队列。在 PriorityQueue中,元素被赋予一个优先级,队列中的元素按照优先级顺序被取出,优先级最低的元素最先被取出。
就相当于在queue原队列基础上给他们赋上了优先级
总结来说,Queue 保证元素的先进先出顺序,而 PriorityQueue 则根据元素的优先级来决定取出顺序。选择哪一个取决于你的应用场景,如果你需要按照特定的顺序处理元素,那么PriorityQueue是合适的选择;如果你只需要按照插入顺序处理元素,那么 Queue 就足够了。
PriorityQueue的基本操作
# PriorityQueue的基本操作
pq = queue.PriorityQueue()
pq.put([priority,value]) # 进队列
pq.get() # 取出队首
# put函数的第一个参数priority表示数据的优先级
# 第二个参数value是值,值越小优先级越高
# 队首总是最小值。
import queue # 引入queue库
pq = queue.PriorityQueue() # 创建一个队列
pq.put([1, 'abc']) # 插入队列,同时赋予优先级
pq.put([7, 998])
pq.put([5, True])
while not pq.empty(): # 全部取出(按优先级)
print(pq.get(),end=' ')
# [1, 'abc'] [5, True] [7, 998]
优先队列的例题
import queue # 引入queue库
pq = queue.PriorityQueue() # 创建一个队列
n = int(input())
a = list(map(int, input().split()))
for i in range(len(a)):
pq.put(a[i]) # 很巧妙,把金额作为数据优先级
sum = 0
while pq.qsize()>1: # 全部取出(按优先级)
t = pq.get() + pq.get()
sum += t
pq.put(t)
print(sum)
# 这个算法的核心思想是将所有元素放入优先级队列中
# 然后不断地取出最小的两个元素进行合并,直到最后只剩下一个元素为止。
# 这个过程中,每次合并都会产生一定的代价,最终的总代价就是所有合并代价之和。
三、栈的实现
栈的实现主要也有三种:
1)利用list来实现栈 ( list复习可以参考这个)
2)用collections.deque来实现栈
3)用queue.LifoQueue实现栈
1.用list实现栈
st =[]
st.append('hello') # 送入栈,功能是push()
st.append('world')
st.append(453)
print(st) # ['hello’,’world', 453]
print(len(st)) # 栈的长度 # 3
print(st[len(st)-1]) # 打印栈顶,功能是top() # 453
print(st[-1]) # 打印栈顶,功能是top() # 453
print(st.pop()) # 弹出栈顶 # 453
print(st.pop()) # 弹出栈顶 # world
print(st.pop()) # 弹出栈顶 # hello
print(st) # []
if st:
print("Not Empty") # 是否为空,功能是empty()
else:
print("Empty") # Empty
2.用collections.deque来实现栈
from collections import deque
st = deque()
st.append('hello')
st.append('world')
st.append(453)
print(st) # ['hello’,’world', 453]
print(len(st)) # 栈的长度 # 3
print(st[len(st)-1]) # 打印栈顶,功能是top() # 453
print(st[-1]) # 打印栈顶,功能是top() # 453
print(st.pop()) # 弹出栈顶 # 453
print(st.pop()) # 弹出栈顶 # world
print(st.pop()) # 弹出栈顶 # hello
print(st) # deque([])
if st:
print("Not Empty") # 是否为空,功能是empty()
else:
print("Empty") # Empty
3.用queue.LifoQueue实现栈
from queue import LifoQueue
st = LifoQueue(maxsize = 100)
st.put('hello')
st.put('world')
st.put(453)
print(st.qsize()) # 栈的长度 # 3
print(st.get()) # 弹出栈顶 # 453
print(st.get()) # 弹出栈顶 # world
print(st.get()) # 弹出栈顶 # hello
print(st.empty()) # 是否为空 # True
四、一个省赛例题
解法:
暴力法
>>从第一棵竹子开始,从头到尾,找到相同高度的竹子,砍掉这一段竹子。循环做这个操作,直到所有高度都变为1。
>>复杂度:从左到右遍历一次O(n),可能遍历很多轮,总复杂度大于O()。只能通过20%的测试。
from math import *
n = int(input())
a = list(map(int,input().split()))
ans = 0
while True:
idx = 0
for i in range(n):
if a[i]> a[idx]:
idx= i
if alidx]==1:
break # 全部高度都是1,退出
val = a[idx]
for i in range(idx, n):
if ali] != val:
break # 砍一段相同高度竹子。如果高度不连续,跳出
a[i]= floor(sqrt(floor(a[i]/2)+1)) # floor()向下取整
ans + 1
print(ans)
利用栈
>>首先计算最多砍多少刀,计算每棵竹子砍到1需要多少刀,所有竹子砍数相加得到一个总数,记为ans;
>>记录每棵竹子每次被砍后的新高度:
>>比较任意两个相邻的竹子,它们是否有相同的高度,如果有相同的高度,这两棵竹子接下来可以一起砍,从而少砍一刀,ans减一;
>>比较结束后,ans就是答案。
from math import *
f=[[0]*10 for _ in range(200010)] #二维数组初始化
stk =[0]*10 #一维数组初始化
n = int(input())
a = list(map(int,input().split()))
ans = 0
for i in range(n):
x = a[il; top =0
while x>l:
top += 1;stk[top]=x
x= floor(sqrt(floor(x/2)+1))
ans += top
k=top;j=0
while k>0:
f[i][j]=stk[k]; k -= 1;j += 1
for j in range(10):
for i in range(1,n):
if f[i][j]>0 and f[i][j] == f[i-1][j]:
ans -= 1
print(ans)
>>f[][]记录每棵竹子被砍后的高度,f[i][j]记录第i棵竹子被砍后的高度,f[i][0]是砍最后一刀后的高度,f[i][top]是第一次被砍后的高度。
>>用手写栈stk[]记录砍每刀后的高度,然后赋值给f[i][]。
>>比较任意两棵相邻竹子的高度,如果有某个高度相等,可以一起砍,从而少砍一刀。
>>代码的复杂度:两个for循环计算M×n=10×n次,是O(n)的。总复杂度为O(n)。
总结
在本文中,我们讨论了队列和栈这两种基本的数据结构,以及如何使用Python来实现它们。
首先,我们介绍了队列和栈的定义和特性。队列是一种先进先出(FIFO)的数据结构,而栈是一种后进先出(LIFO)的数据结构。
然后,我们展示了如何使用Python的queue库来实现一个队列。我们使用Queue类创建了一个线程安全的队列,并演示了如何进行入队(put)、出队(get)和查询队列大小(qsize)的操作。
接着,我们介绍了如何使用Python的list
和collections.deque
来实现队列。我们通过在列表的末尾添加元素来实现入队操作,通过翻转列表来模拟出队操作。而deque
提供了一个更高效的方法来实现队列,因为它在两端都可以快速地进行添加和删除操作。
我们还讨论了如何使用collections.deque
来实现栈。栈的入栈操作可以通过append
方法来实现,而出栈操作可以通过pop
方法来实现。deque
同样可以用来实现一个高效的单调栈。
最后,我们通过一个省赛例题来展示了栈的应用。我们使用了栈来解决这个问题,从而减少了对每个元素进行比较的次数,提高了算法的效率。
总的来说,本文通过详细的代码示例和解释,介绍了队列和栈这两种基本数据结构的实现和应用。希望这些内容能够帮助读者更好地理解队列和栈的概念,并能够在实际编程中灵活运用它们。
(好欸,庆祝我找到了属于我的阳菜 她好漂亮 我很喜欢她!!!爱她!!!)