优先队列
引入
在生产调度中,事件都有优先级,那么如何快速的调度最高优先级的事件成为一件需要考虑的事情。调度中有两种操作,第一种是调度最高级事件,第二种是插入事件,那么优先队列这种数据结构完美解决了这两个操作,在优先队列中这两种操作完成的任务就是删除队列中最大值和插入新值。
优先队列初级实现
那么优先队列如何实现呢?简单的可以用数组来实现,有以下两种方法:
1.数据插入随意,数据是无序的,删除时利用选择排序中的一次内循环找出最大值并删除。
2.数据插入时利用插入排序进行插入,数据是有序的,删除时直接删除最右端的值便可以。
那么这样实现的优先队列操作的时间复杂度怎么样呢?
方式 | 插入元素 | 删除最大元素 |
---|---|---|
无序 | 1 | M(最坏情况为N) |
有序 | M(最坏情况为N) | 1 |
二叉堆引入
由于初级实现的优先队列的两种操作时间复杂度在N较大时效果不好,引入了二叉堆的数据结构,两种操作的数量级均可以达到logN。
概念
堆有序:树中的每个节点均大于等于它的两个子节点。
完全二叉树:除最深一层外其他层节点均达到最大值,且最深一层连续集中在左边的二叉树(完全二叉树可以与数组一一对应)
二叉堆:一组能够用堆有序的完全二叉树排序的元素,并在数组中按层级存储。
二叉堆实例:
堆操作
删除堆中的最大值:将根节点删除,并将最末尾元素放至根节点,然后将该元素进行下沉操作。
插入新值:插入至末尾,并将该元素进行上浮操作
下沉操作代码:
void sink(int k)
{
while(2*k<=N){
int j=2*k;
if(j<N&&less(j,j+1)) j++;
if(!less(k,j)) break;
exch(k,j);
k=j;
}
}
上浮操作代码: