优先队列Priority Queue和堆Heap
对COMP20003中的Priority queue部分进行总结。图片来自于COMP20003
queue队列,顾名思义特点先进先出
priority queue优先队列,出来的顺序按照优先级priority大小,越大(小)的先pop。
普通的方法:
Unsorted array:
Construct: O(n)
Get highest priority: O(n)
Sorted array:
Construct: O(n2)
Get highest priority: O(1)
使用堆heap方法则可以:
Construct:O(n)
Get hishest priority: O(1)
heap data structre: 完全树的数组(指针)形式(不一定是二叉树)。其每个节点满足优先级高于它的子节点,但左右子节点并没有大小关系。 本文主要讲binary heap形式的。
从根节点开始编号放入数组中,为了后续操作方便,可以将数组[0]空出不用,从1开始(如上图,下面的文字叙述也按从1开始,将数组叫做A),因为完全树的关系,如果一个节点是A[i],则它的两个子节点则是A[2 * i]和A[2 * i + 1]。
假定优先级越高越靠前,则第一个节点是(优先级)最大的,之后的都比它小,但左子树上的点和右子树上的点大小关系并不确定。
当pop时,将第一个节点排出,将最后一个节点放到第一个节点的位置,然后从第一个节点位置开始进行downHeap操作修复堆(使得每个节点满足优先级高于它的子节点)。
当push时,将新插入的节点接在末尾,从末尾开始进行upHeap操作修复堆(使得每个节点满足优先级高于它的子节点)。
downHeap:从指定节点位置A[i]开始,与其两个子节点A[2 * i]和A[2 * i + 1]进行优先级比较(或与两个子节点中较大的那个进行比较),如果是A[i]最大,则停止,如果不是,则和较大的那个子节点交换位置,再继续与子节点进行比较,直到没有子节点时停止。
upHeap:从指定位置A[i]开始,与其根节点A[i / 2]进行比较,如果根节点大,则停止,否则交换位置继续与根节点比较,直到没有根节点为止。
两种建堆方法:
1.插入一个节点,进行一次upHeap操作修复堆。 总复杂度O(nlogn)
2.将全部节点插入后,从A[n / 2]到A[1]进行upHeap操作修复堆,即heapSort。看似复杂度还是O(nlogn),但实际上是O(n),因为只有一半的节点需要进行upHeap操作且只有A[1]的upHeap是O(logn),数学证明不懂,以后看看有没有时间补吧。。。
我的代码:
https://raw.githubusercontent.com/Will-Zhu-27/Algorithms-and-Data-Structures/master/priorityQueue.c
https://raw.githubusercontent.com/Will-Zhu-27/Algorithms-and-Data-Structures/master/priorityQueue.h