创建病人低优先级队列怎么解除列

该楼层疑似违规已被系统折叠 

低低优先级队列怎么解除列无法解除提示只有5局,可是我玩了快100局了还是5局


}

优先队列是计算机科学中的一类抽象数据类型优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;優先级相同的元素按照其在优先队列中的顺序得到服务优先队列往往用堆来实现。


在医院门诊如果只有一个医生,多位病人按照通常流程来说,采用先到先服务的顺序(FIFO)但是如果病人中有人患有心脏病,那么显然这个病人需要得到优先治疗
在计算机系統中,绝大多数支持多任务这种多任务调度也类似于医院门诊。CPU相当于医生计算任务相当于病人。每个任务都有一个优先级指标(priority)优先级高的任务可以被CPU优先处理。
在算法中也有大量应用。比如堆排序、霍夫曼编码等


以上问题可以被归纳为这样一种模式:服务端(医生、CPU、霍夫曼算法…)通过一种叫call-by-priority(循优先级访问)的方式访问客户数据(病人,任务待编码字符…),客户数据都有┅个优先级指标这种访问方式需要对应一种数据结构,可以记录、维护所有数据的优先级指标并通过接口对这些数据进行操作。


以上为低优先级队列怎么解除列(简称PQ)的接口定义规范可以说PQ是一种抽象数据类型(ADT),不同的实现方式可以产生不同的数据结構比如栈和队列(根据插入次序设置优先级)。
那么这样一种数据结构具体怎么实现呢?

采用不同数据结构实现PQ的接口效率對比

虽然BBST的效率是最好的但是BBST的功能比PQ需要实现的功能多得多:比如PQ对于查找和删除只针对最大元素,而BBST是针对所有元素
因此可以使鼡一种成本更低,效率更高的实现方式这种结构应该介于基本数据结构向量和复杂数据结构平衡二叉树之间。

要介绍完全二叉堆先要介绍。这里通过使用向量来表示一个完全二叉树从而实现PQ结构。
1. 可以看到完全二叉树的节点与向量的节点是一一对应的(层佽遍历)只要定义向量的每个节点的父节点、左孩子和右孩子,即可构建出完全二叉树
2. 这种做法的好处是:物理结构是线性的向量,泹是逻辑结构是完全二叉树这种结构称为“完全二叉堆”。
可以看到其作为PQ实现了insert,getMax,delMax三个标准接口,还实现了批量建堆的接口另外,這些接口的实现利用了三个内部方法:下滤、上滤和Floyd建堆算法

堆排序和选择排序的方法类似。

选择排序(Selection sort)是一种简单直观的排序算法它的工作原理如下。首先在未排序序列中找到最小(大)元素存放到排序序列的起始位置,然后再从剩余未排序元素中继续尋找最小(大)元素,然后放到已排序序列的末尾以此类推,直到所有元素均排序完毕

堆排序也是不断调用delMax方法取出堆顶最大元素进荇排序。
但是堆排序相对于选择排序O(n^2)的时间复杂度更高效:每次delMax为logn时间一共只需nlogn。不仅在时间上堆排序在空间上也很高效。
由于堆是建立在向量基础上我们可以充分利用向量空间,使空间复杂度为常数如上图,将向量空间分为堆空间和已排序元素两个部分不断从堆空间取出最大元素并移至已排序空间,同时将堆空间最后一个元素移至堆顶反复这个过程,直至堆空间为空

左式堆的设计是為了堆的高效合并。
一种直接的合并方法是:先将两个堆连接在一起再通过建堆算法建堆。这种算法的效率为O(n+m)
在建堆算法中,默认所囿元素都是无序的而现在要合并的两个堆都是已经满足堆序性的结构,因此理论上存在更优的合并策略这种策略就是引用左式堆。
左式堆是一种特别的堆结构它满足堆序性,却不满足堆结构:它不是一棵完全二叉树对于堆而言,结构并不是本质要求

  • 为了使左式堆茬逻辑意义上满足二叉树结构,可以引入空节点来填补节点空缺NPL(空节点路径长度),是指一个节点到一个外部节点的最小距离用来衡量左式堆倾斜度的指标。

  • 任意一个节点的左孩子的npl值都大于等于其右孩子的npl值
    那么对于含有n个节点的左式堆而言,其右侧链长度应为logn

  • 咗式堆由于不再满足完全二叉树结构,物理上的紧凑性也难以满足此时再使用向量已不适宜,转而采用二叉树作为派生基类模板类如丅:
    左式堆合并的思路为:存在两个左式堆A,B,假设A的根节点大于B那么以递归的方法,将A的右子堆与堆B合并合并完成后的堆继续作为A的祐子堆。在合并完成后还需要检查A的左孩子和右孩子的NPL值,如果NPL(L)小于NPL(R)将左右孩子替换。
    上图为两个左式堆合并的完整过程代码如下:
    由于左式堆合并过程一直在右侧链进行,因此其时间复杂度不会超过右侧链的长度logn

  • 左式堆的插入其实也是合并操作,将带插入的节点視为只有一个节点的二叉树与原堆进行合并,即实现了插入操作
    删除操作也是合并。在左式堆的根节点被删除之后将剩下的左右子堆合并成新的左式堆即可。
    由于合并操作的时间复杂度为O(logn),插入删除操作的时间复杂度也为O(logn)

  1. 从需求出发,存在一种“循优先级访问”嘚方式必须设计这样一种数据结构满足这个要求,这个结构称为“低优先级队列怎么解除列”(PQ)
  2. 对PQ的功能做了定义之后,分别计算叻使用现有数据结构实现的效率发现只有BBST可以达到三个操作都是O(logn)的时间。但是BBST作为一种高级数据结构其功能远大于PQ。引出堆这样一种較BBST简单但效率不低于BBST的结构
  3. 介绍完全二叉堆的结构和堆序性特点,以及其三个内部方法:上滤、下滤和Floyd建堆发现其三个标准接口的效率为O(1),O(logn),O(logn)。
  4. 根据堆的堆序性特点可以对元素进行排序即每次把最大元素删除即可。堆排序的时间复杂度为nlogn
  5. 堆在很多方面效率都很高,但在堆的合并上的效率不太让人满意由此派生出左式堆这一结构完成堆的高效合并。左式堆的逻辑结构不再是完全二叉树物理结构换成了②叉树。其重要的特性是NPL保证了合并的效率为O(logn),且插入删除操作也保持在O(logn)。
}

这一篇是《流畅的 python》读书笔记主要介绍列表、列表推导有关的话题,最后演示如何用列表实现一个低优先级队列怎么解除列

Python 标准库用 C 实现了丰富的序列类型:

容器序列存放的是它们所包含的任意类型的对象的引用,而扁平序列里存放的是值而不是引用(也可以说扁平序列其实存放的是一段连续的内存涳间)

如果按序列是否可被修改来分类,序列分为可变序列不可变序列:

从这个图可以看出可变序列从不可变序列那里继承了一些方法。

列表推导和生成器表达式

列表(list)是 Python 中最基础的序列类型list 是一个可变序列,并且能同时存放不同类型的元素
列表的基础用法这里僦不再介绍了,这里主要介绍一下列表推导

列表推导是构建列表的快捷方式,并且有更好的可读性

#2. 把一个字符串变成 unicode 码位的列表 使用列表推导

对比发现,如果理解列表推导的话第二段代码比第一段更简洁可读性也更好。
当然列表推导也不应该被滥用,通常的原则是呮用列表推导来创建新的列表并且尽量保持简短。
如果列表推导超过两行就应该考虑要不要使用 for 循环重写了。

在 Python2 中列表推导有变量泄露的问题

这里 x 原来的值被取代了变成了列表推导中的最后一个值,需要避免这个问题好消息是 Python3解决了这个问题。

可以看到这里 x 原有嘚值被保留了,列表推导也创建了正确的列表

列表推导还可以生成两个或以上的可迭代类型的笛卡尔积。

笛卡尔积是一个列表列表里嘚元素是由输入的可迭代类型的元素对构成的元组,因此笛卡尔积列表的长度等于输入变量的长度的成绩如图所示:

# 使用列表推导计算笛卡尔积代码如下

这里得到的结果是先按数字排列,再按图案排列如果想先按图案排列再按数字排列,只需要调整 for 从句的先后顺序

问題:你有一个数据序列,想利用一些规则从中提取出需要的值或者是缩短序列

最简单的过滤序列元素的方法是使用列表推导比如:

使用列表推导的一个潜在缺陷就是若干输入非常大的时候会产生一个非常大的结果集,占用大量内存这个时候,使用生成器表达式迭代产生過滤元素是一个好的选择

生成器表达式遵守了迭代器协议,可以逐个产出元素而不是先建立一个完整的列表,然后再把这个列表传递箌某个构造函数里

生成器表达式的语法跟列表推导差不多,只需要把方括号换成圆括号

# 使用生成器表达式创建列表

如果生成器表达式昰一个函数调用过程中唯一的参数,那么不需要额外再用括号把它围起来例如:

如果生成器表达式是一个函数调用过程中其中一个参数,此时括号是必须的比如:

怎么实现一个按优先级排序的队列?并在这个队列上每次 pop 操作总是返回优先级最高的那个元素

heapq 是 python 的内置模块源码位于 Lib/heapq.py ,该模块提供了基于堆的优先排序算法

堆的逻辑结构就是完全二叉树,并且二叉树中父节点的值小于等于该节点的所有子节點的值这种实现可以使用 heap[k] <= heap[2k+1] 并且 heap[k] <= heap[2k+2] (其中 k 为索引,从 0 开始计数)的形式体现对于堆来说,最小元素即为根元素 heap[0]

heapq 提供的一些方法如下:

通過执行结果我们可以发现,第一个 pop() 操作返回优先级最高的元素两个优先级相同的元素(foo 和 grok),pop 操作按照它们被插入到队列的顺序返回

函数 heapq.heappush() 和 heapq.heappop() 分别在队列 queue 上插入和删除第一个元素,并且队列 queue 保证 第一个元素拥有最小优先级 heappop() 函数总是返回 最小的 的元素,这就是保证队列 pop 操莋返回正确元素的关键另外,由于 push 和 pop 操作时间复杂度为 O(log N)其中 N 是堆的大小,因此就算是 N 很大的时候它们 运行速度也依旧很快

在上面代碼中,队列包含了一个 (-priority, index, item) 的元组优先级为负 数的目的是使得元素按照优先级从高到低排序。这个跟普通的按优先级从低到高排序的堆排序恰巧相反index 变量的作用是保证同等优先级元素的正确排序。通过保存一个不断增加的 index 下标变量可以确保元素按照它们插入的顺序排序。洏且 index 变量也在相 同优先级元素比较的时候起到重要作用。

实现上边排序的关键是 元组是支持比较的:

当第一个值大小相等时由于Item 并不支持比较会抛出 TypeError。为了避免上述错误我们引入了index(不可能用两个元素有相同的 index 值), 变量组成了(priority, index, item) 三元组现在再比较就不会出现上述问題了:

主要介绍列表、列表推导有关的话题,最后演示如何用heapq列表实现一个低优先级队列怎么解除列下一篇介绍元组


最后,感谢女朋伖支持

}

我要回帖

更多关于 低优先级队列怎么解除 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信