蓝桥杯Python人的自我救赎——基础数据结构(3)

说在前面——摆烂人的觉醒

假期没好好学,现在开始救赎自己,争取300元子不白给了(大哭)(已经白给了)

从现在开始我根据视频课来总结知识点(纯干货),并且做题练手!大家一起加油!!


文章目录

说在前面——摆烂人的觉醒

前言

一、队列和栈是什么

队列是什么?

栈是什么?

二、队列的实现

0.一个例题

1.用queue实现队列

2.用list实现队列

3.用deque实现队列

 4.Python优先队列

PriorityQueue的基本操作

优先队列的例题

三、栈的实现

 1.用list实现栈

2.用collections.deque来实现栈

3.用queue.LifoQueue实现栈

 四、一个省赛例题

 解法:

 暴力法

利用栈 

总结 


前言

我先从基础数据结构开始,前面的基础操作先略过,我最后填坑
这一章是基础数据结构,主要内容有数组,链表,队列和栈 还有 二叉树
这一篇主要讲解队列和栈(链表的话看上一篇)
以及一些相关习题


一、队列和栈是什么

队列是什么?

队列,就像他的名字一样,先到先得,先来的同学先打饭

特点:先进先出

        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(n^{_{2}})。只能通过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的listcollections.deque来实现队列。我们通过在列表的末尾添加元素来实现入队操作,通过翻转列表来模拟出队操作。而deque提供了一个更高效的方法来实现队列,因为它在两端都可以快速地进行添加和删除操作。

        我们还讨论了如何使用collections.deque来实现栈。栈的入栈操作可以通过append方法来实现,而出栈操作可以通过pop方法来实现。deque同样可以用来实现一个高效的单调栈。

        最后,我们通过一个省赛例题来展示了栈的应用。我们使用了栈来解决这个问题,从而减少了对每个元素进行比较的次数,提高了算法的效率。

        总的来说,本文通过详细的代码示例和解释,介绍了队列和栈这两种基本数据结构的实现和应用。希望这些内容能够帮助读者更好地理解队列和栈的概念,并能够在实际编程中灵活运用它们。

(好欸,庆祝我找到了属于我的阳菜  她好漂亮  我很喜欢她!!!爱她!!!)

  • 27
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值