优先队列

1.优先队列的概念

优先队列也是和栈/队列一样的缓存结构,但是它的独特点在于:每个进入缓存的元素都会附有一个数值,这个数值代表着取用时的先后顺序。

举一个简单的例子:我把附带优先数值2 3 1 5 4的元素,依次放入优先队列;尽管先放进去的是附加值为4的元素,但是它不会像队列一样,最先被取出;尽管最后放入的是附加值为2的元素,但是它也不会像栈一样,优先被弹出;它的正确取出方式是按照附加值从小到大(或者从大到小被取出)

2.优先队列的实现方式之一

我们可以用线性表去实现:每次把元素按照附加值,插入到线性表当中;但是这样插入的复杂度是O(n),取出为O(1)。

此类的实现方式简单;这里不必多言。

3.优先队列的实现方式之二

在学习了二叉树之后

我们可以利用完全二叉树去实现这种结构,完全二叉树的层次结构可以有效降低线性表的线性插入复杂度。

具体我们可以做如下分析

1.利用二叉树实现堆是基础

堆的概念:一个 父节点必须小于(大于)子节点的 完全二叉树。(从每一个叶节点向上到根节点都是有序的)

2.在堆中插入元素

插入元素:① 先放在原来堆的末尾;当这个新添元素的父元素序号( (p-1)//2 )大于0的时候

                  ② 然后执行向上筛选

                   最后 当这个父亲元素序号 == 0 时:执行最后一次向上筛选。

附:向上筛选:

向上筛选每次只要和父节点比就行(向下筛选要和两个子节点相比),具体如下

首先:输入向上筛选的起始元素,在父节点序号大于0的时候;比较父子节点大小,满足子小于父节点,调换;更新起始元素;回到首先处;当起始元素更新到它的父元素的序号是0的时候;执行最后一次向上筛选;结束。

 

3.从完全二叉树中建堆

①可以利用2的方法,将完全二叉树的元素一一插入,从而建立堆;但是这样复杂度略高

②在重整完全二叉树建堆

先找到原始完全二叉树的最后一个元素;再找它的父节点(son//2 -1);从这个父节点向下筛选;然后找这个父节点所在的序号的前一个元素;向下筛选;就这样直到序号为0时结束。

附:向下筛选:

首先,我们已经有了这个父节点的序号;在保证这个父节点的两个子节点都在的情况下 找到这个父节点的两个子节点;再将父节点和这两个子节点比较,把最小的放在父节点的位置;更新这个父节点,使这个父节点进入子代;再回到开始的地方。当这个父节点的一个子节点不在了;比较父节点和唯一的子节点;结束整个向下筛选;当这个父节点两个子节点都不在了;结束整个向下筛选。

小结:本节逻辑完全正确,具体代码实现需要注意的细节也在代码内标注:见文章底部

4.删除元素

① 删除根节点;然后把末尾的元素放到根节点的位置

② 做一次向下筛选

5. 优先队列API

1、heappush(heap, x):向堆中添加元素

from heapq import * 
heap = [] for i in range(3): 
    heappush(heap, i) 
print(heap) #[0, 1, 2]
heappush(heap, 0.5) 
print(heap) #[0, 0.5, 2, 1]
heappush(heap, 1.5) 
print(heap) #[0, 0.5, 2, 1, 1.5]

2、heappop(heap):弹出堆中最小的元素,并且维持剩余元素的堆结构。

3、heapify(heap):将列表转换为堆。

4、heapreplace(heap, x):弹出堆中最小的元素,然后将新元素插入。

5、nlargest(n, iter)、nsmallest(n, iter):用来寻找任何可迭代对象iter中的前n个最大的或前n个最小的元素。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值