1、优先队列的一些简单的实现:ios
1. 使用一个简单的链表在表头以O(1) 执行插入操做,并遍历该链表以删除最小元,这须要O(N) 的时间。数组
2. 始终让表保持有序状态;这使得插入代价高昂(O(N)), 而删除代价低廉(O(1))。基于删除最小元的操做从很少于插入操做的事实,所以,前者是更好地想法。数据结构
3. 使用二叉查找树,它对这两种操做的平均运行时间是O(logN)。尽管插入是随机的,而删除不是,但这个结论仍是成立的。因为删除的惟一元素是最小元。反复除去左子树中的节点彷佛损害树的平衡,使得右子树加剧。然而,右子树是随机的。在最坏的情形,即将左子树删空的情形,右子树拥有的元素最多。(查找树中有许多并不须要的操做)工具
4. 将要使用的工具二叉堆(堆):它的使用对于优先队列的实现是如此的广泛。spa
2、 堆具备两个性质:结构性质和堆序性质指针
1)结构性质:堆是一棵被彻底填满的二叉树,有可能的例外是在底层,底层上的元素从左到右填入,即为:一棵彻底二叉树。code
一棵高为 h 的彻底二叉树的节点数为 2^h ~ 2^(h+1)-1。这意味着彻底二叉树是O(logN)。队列
由于彻底二叉树颇有规律,因此它能够用一个数组表示,而不使用指针。对数组中任意位置 i 上的元素,其左孩子在 2i 位置处,右孩子在左孩子的后一单元(2i+1)中,它的父节点在 i / 2(下取整) 上。这种实现惟一的问题在于,最大的堆大小须要事先估计,但对于典型的状况这并不成问题。it
所以,一个堆的数据结构将由一个数组(无论关键字是什么类型)、一个表明最大值的整数,以及当前的堆大小组成。io
#define MINQUSIZE 5
#define MinData 0.0001
typedef int ElemType;
typedef struct HeapStruct
{
ElemType *elem;
int Capasity;
int Size;
}Heap, *PriorityQueue;
2)堆序性质:使操做被快速执行的性质是堆序性,因为要快速的找出最小元,所以,最小元应该在根上。考虑任意子树也应该是一个堆,那么仁义节点应该小于它的全部后裔。
在一个堆中,对于每个节点X, X的父亲中的关键字小于(或等于)X 中的关键字,根节点除外(它没有父亲)。
3、基本操做:
1)插入(Insert):为将一个元素X 插入堆中,咱们在下一个空闲位置(数组末尾)建立一个空穴,不然,该堆就不是彻底树。若是X 能够放在空穴中,而并不破坏堆的序,那么插入完成。不然,将空穴的父节点上的元素放入空穴中,这样空穴的位置就朝着跟的方向上移一个位置。继续该过程直至 X 能被放入空穴中为止。这一操做称之为上滤。
void InsertHeap(ElemType value, PriorityQueue H)
{
int i;
if(H->Size == H->Capasity) //堆已满
return;
for(i = ++H->Size; H->elem[i / 2] > value; i /= 2)
{
H->elem[i] = H->elem[i / 2]; //父节点下移
}
H->elem[i] = value;
}
2) 删除操做(DeleteMin):删除最小元。当删除最小元时,在根节点处产生了一个空穴。因为如今堆少了一个元素,所以堆中最后一个元素 X 必须移动到该堆的某个位置。若是 X 能够被放到空穴中,那么删除操做完成。这通常不太可能完成,所以,将空穴的两个儿子中较小的一个移入空穴,这样就把空穴向下推了一层。重复该步骤直到 X 能够被放入空穴中。所以,咱们的作法是将 X 置入从根开始包含最小儿子的一条路径上的一个正确位置。
ElemType DeleteMin(PriorityQueue H)
{
int i, child;
ElemType MinElem, LastElem;
if(H->Size == 0)
{
cout << "PriorityQueue is empty." << endl;
return H->elem[0];
}
//堆的创建 #include<iostream> #define MINQUSIZE 5 #define MinData 0.0001 using namespace std; typedef int ElemType; typedef struct HeapStruct { ElemType *elem; int Capasity; int Size; }Heap, *PriorityQueue; PriorityQueue InitializeHeap(int MaxSize) { PriorityQueue H; if (MaxSize < MINQUSIZE) throw("Priority queue size is too small."); H = new HeapStruct(); H->elem = new int[MaxSize + 1]; H->Capasity = MaxSize; H->Size = 0; H->elem[0] = MinData; return H; } void InsertHeap(ElemType value, PriorityQueue H) { int i; if(H->Size == H->Capasity) //堆已满 return; for(i = ++H->Size; H->elem[i / 2] > value; i /= 2) { H->elem[i] = H->elem[i / 2]; //父节点下移 } H->elem[i] = value; } ElemType DeleteMin(PriorityQueue H) { int i, child; ElemType MinElem, LastElem; if(H->Size == 0) { cout << "PriorityQueue is empty." << endl; return H->elem[0]; } MinElem = H->elem[1]; LastElem = H->elem[H->Size--]; for(i = 1; i *2 <= H->Size; i = child) { child = i * 2; //i 的左孩子 if(child != H->Size && H->elem[child] > H->elem[child + 1]) child++; if(LastElem > H->elem[child]) H->elem[i] = H->elem[child]; //空穴下移 else break; } H->elem[i] = LastElem; return MinElem; } int main() { PriorityQueue H; H = InitializeHeap(10); for(int i = 1; i < 8; i++) InsertHeap(i, H); for(int j = 0; j <= H->Size; j++) cout << H->elem[j] << " "; cout << endl; DeleteMin(H); for(int j = 0; j <= H->Size; j++) cout << H->elem[j] << " "; system("pause"); return 0; }