第03章 基本数据结构——队列

队列

队列的定义

队列是有序集合, 添加操作发生在“尾部”, 移除操作则发生在“头部”。 新元素从尾部进入队列, 然后一直向前移动到头部, 直到成为下一个被移除的元素。

最新添加的元素必须在队列的尾部等待, 在队列中时间最长的元素则排在最前面。 这种排序原则被称作 FIFO ( first-in first-out) ,即先进先出, 也称先到先得。

书本上的python实现

class Queue:
    def __init__(self):
        self.items = []

    def isEmpty(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)

这个实现显然不好,因为列表的insert的复杂度是O(n)的,这在我们之前的文章中说过了,这导致实现速度非常的慢。而python内部有queue库的实现,这里就进行两者的对比看看。

from pythonds.basic import Queue as q1
from time import time
import queue as q2

q_1 = q1()
q_2 = q2.Queue()

start = time()
for i in range(100000):
    q_1.enqueue(i)
end = time()

print(end-start)  # 5.54210090637207

start = time()
for i in range(100000):
    q_2.put(i)
end = time()
print(end-start)  # 0.3688485622406006

因此,我们应该使用python内部实现的,而非本书提供的方式。

queue模块

接下来先简单介绍一下queue.Queue的功能,queue模块其实也有栈的实现(大家可以自行查阅相关资料),但是由于python的append和pop的实现是O(1)的,所以之前的文章就直接这样使用了。

from queue import Queue

q = Queue(maxsize=3)  # maxsize表示队列的容量 当maxsize 小于等于 0时 表示无限容量
for i in range(3):
    q.put(i)  # 往队列中添加元素
print(q.empty())  # 表示队列是否为空
print(q.full())  # 判断队列是否为满
print(q.qsize())  # 返回队列中的元素个数

for j in range(3):
    q.get()   # 从队列中拿出元素
    
for i in range(3):
    q.put_nowait(i)  # 这个也是会往队列添加元素

for i in range(3):
    q.get_nowait()  # 这个也是从队列中拿东西
    
    
### xxx_nowait 和 xxx的区别
"""
先讲结论 一般情况下
在多进程中使用get 和 put
在单进程中使用get_nowait和put_nowait

原因是 get 和 put 当队列没元素时,
他不会报错而是程序持续运行 等待队列更新元素,这显然只有在多进程中可以实现

而get_nowait 和 put_nowait 则不会等待队列更新,而是直接报错,
"""

约瑟夫斯问题

这本书在队列这里提供了两个应用,一个是约瑟夫斯问题还有一个是打印机的问题,由于打印机的问题稍微有点复杂,篇幅写起来就很长了,就先讲一个约瑟夫斯问题,后面专门搞一篇文章讲打印机的问题。

先简单介绍一下约瑟夫斯问题的背景:弗拉维奥·约瑟夫斯是公元 1 世纪著名的历史学家。 相传, 约瑟夫斯当年和 39 个战友在山洞中对抗罗马军队。 眼看着即将失败, 他们决定舍生取义。 于是,他们围成一圈, 从某个人开始, 按顺时针方向杀掉第 7 人。 约瑟夫斯同时也是卓有成就的数学家。 据说, 他立刻找到了自己应该站的位置, 从而使自己活到了最后。 当只剩下他时, 约瑟夫斯加入了罗马军队, 而不是自杀。 这个故事有很多版本, 有的说是每隔两个人,有的说最后一个人可以骑马逃跑。 不管如何, 问题都是一样的。

这个问题怎么处理呢?其实就是使用一个队列,不断的出列,入列,然后通过一个变量去记录1-7的数字,然后数字变七,就出列不入列,直到最后只剩一个人。

书上的那个结果是有问题的,他的结果是6个玩这个游戏,答案是3,下面是我们的画图解法,显然最后的结果是5,所以书上的那个解法是错误的。

请添加图片描述

代码实现

from queue import Queue

q = Queue()
n = 1
for i in range(1, 41):
    q.put(i)

while q.qsize() > 1:  # 留到只剩最后一个人为止
    if n == 7:  # 第七个就重新计数 然后出列一个
        n = 0
        q.get()
    else:  # 其他情况就是出列入列
        temp = q.get()
        q.put(temp)
    n += 1  # 变量的记录
    
print("最终的胜利者的序号为%d" % q.get())

代码浅运算了一下,反正大概就是说40个人,每七个杀一个人,那么最后你选24的位置,你就可以活下来了。

然后下一篇博客就把那个打印任务单独拿出来处理掉

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值