队列的特点是先进先出。通常都把队列比喻成排队买东西,大家都很守秩序,先排队的人就先买东西。
但是优先队列有所不同,它不遵循先进先出的规则,而是根据队列中元素的优先权,优先权最大的先被取出。通常把优先队列比喻成现实生活中的打印。一个打印店里有很多打印机,每台机器的性能不一样,有的打印机打印很快,有的打印机打印速度很慢。当这些打印机陆陆续续打印完自己的任务时进入排队等候状态。如果我这个时候要打印一份文件,我选的不是第一个排队的打印机,而是性能最好,打印最快的打印机。
优先队列的特点就是将存储的元素根据其优先权的高低,先取出优先权高的元素。所以,优先队列的实现方法有很多。
如果优先权的范围是已知的,那么就可以尝试用一个二维数组来实现优先队列。每一行表示一个优先级别。例如用大小为a[10][10]的二维数组来实现一个优先队列,a[0]表示一个优先级别,里面存放优先级为0的元素,a[10]则存放优先级最高的元素。这样根据元素的优先级进行存储,取出元素的时候,根据优先级,先取出优先级最高的元素。
上面的方法在优先权范围已知且比较集中可以估计的情况下可以适用,但是如果优先权的范围不清楚,或者间隔很大,就不再使用。实现优先队列也可以用一个链表队列加以实现。链表的节点数据包含两个部分,队列的数据项和该数据项的优先权。将元素存入链表,需要用时,遍历链表,查找优先权最大的数据项。
优先队列式分支界限法解装载问题中需要用到最大堆MazHeap,但是书上没有给出代码,所以只能我们自己写了,下面我贴出这两个数据结构的代码,以供参考。解决了这两个数据结构,那么优先队列式分支界限法就很好实现了。
最大堆MaxHeap:
- #include<iostream>
- using namespace std;
- typedef struct Heap
- {
- int capacity;
- int size;
- int *Elem;
- }Heap,*HeapQueue;
- #define MaxData 32767
- HeapQueue init(int maxElem)
- {
- HeapQueue H;
- H=(HeapQueue)malloc(sizeof(Heap));
- H->capacity=maxElem;
- H->size=0;
- H->Elem=(int *)malloc((maxElem+1)*sizeof(int));
- H->Elem[0]=MaxData;
- return H;
- }
- void InsertMax(int x,HeapQueue H)
- {
- int i;
- for(i=++H->size;H->Elem[i/2]<x;i/=2)
- H->Elem[i]=H->Elem[i/2];//此时i还没有进行i/2操作
- H->Elem[i]=x;
- }
- int DeleteMax(HeapQueue H)
- {
- int i,child;
- int MaxElem,LastElem; //存储最大元素和最后一个元素。
- MaxElem=H->Elem[1]; //堆是从第1号元素开始的。
- LastElem=H->Elem[ H->size-- ]; //这里自动让size减少了。
- for(i = 1 ; i * 2 <= H->size ; i = child)
- {
- child=i * 2;
- /*在节点有左右子树的时候,可能存在一个大一个小的情况,这时候我们就要找出最小的;
- 如果Child = H->Size则表明他没有右子树,这时候就没有必要比较了。
- */
- if(child != H->size && H->Elem[child+1]>H->Elem[child])
- child++;//找最大的子树
- // 与 H->Elem[i]=LastElem; 结合,将两个孩子和 lastElement 中较大的放入祖先节点
- if(LastElem < H->Elem[child])
- H->Elem[i]=H->Elem[child];
- }
- H->Elem[i]=LastElem;
- return MaxElem;
- }
- void MakeEmpty(HeapQueue H)
- {
- H->size=0;
- }
- int FindMax(HeapQueue H)
- {
- return H->Elem[1];
- }
- void DestoryH(HeapQueue H)
- {
- free(H->Elem);
- free(H);
- }
- int main()
- {
- HeapQueue H=init(4);
- int i;
- for(i=1;i<=3;i++)
- InsertMax(i,H);
- /*
- cout<<H->size<<endl;
- for(i=1;i<=3;i++)
- cout<<H->Elem[i]<<endl;
- */
- int a=DeleteMax(H);
- cout<<a<<endl;
- return 1;
- }
最小堆MinHeap:
- #include<iostream>
- using namespace std;
- typedef struct Heap
- {
- int capacity;
- int size;
- int *Elem;
- }Heap,*HeapQueue;
- #define MinData -32767
- HeapQueue init(int maxElem)
- {
- HeapQueue H;
- H=(HeapQueue)malloc(sizeof(Heap));
- H->capacity=maxElem;
- H->size=0;
- H->Elem=(int *)malloc((maxElem+1)*sizeof(int));
- H->Elem[0]=MinData;
- return H;
- }
- void Insert(int x,HeapQueue H)
- {
- int i;
- for(i=++H->size;H->Elem[i/2]>x;i/=2)
- H->Elem[i]=H->Elem[i/2];//此时i还没有进行i/2操作
- H->Elem[i]=x;
- }
- int DeleteMin(HeapQueue H)
- {
- int i,child;
- int MinElem,LastElem;
- MinElem=H->Elem[1];//堆是从第1号元素开始的。
- LastElem=H->Elem[H->size--];//这里自动让size减少了。
- for(i = 1 ; i * 2 <= H->size ; i = child)
- {
- child=i * 2;
- /*在节点有左右子树的时候,可能存在一个大一个小的情况,这时候我们就要找出最小的;
- 如果Child = H->Size则表明他没有右子树,这时候就没有必要比较了。
- */
- if(child != H->size && H->Elem[child+1]<H->Elem[child])
- child++;
- if(LastElem>H->Elem[child])
- H->Elem[i]=H->Elem[child];
- }
- H->Elem[i]=LastElem;
- return MinElem;
- }
- void MakeEmpty(HeapQueue H)
- {
- H->size=0;
- }
- int FindMin(HeapQueue H)
- {
- return H->Elem[1];
- }
- void DestoryH(HeapQueue H)
- {
- free(H->Elem);
- free(H);
- }
- int main()
- {
- /*
- HeapQueue H=init(4);
- int i;
- for(i=1;i<=4;i++)
- Insert(i,H);
- int a=DeleteMin(H);
- cout<<a;
- */
- }
本文参考了http://blog.csdn.net/xw13106209/article/details/4942331