首先搞清楚 什么是优先队列,优先队列是一种数据结构,它与一般的队列先入先出的性质不同,它每次出队的是优先级最大的元素,当一个指定的优先级元素入队时,能够很快的把它排到队列中。看到这里,可以发现,优先队列其实就是堆排序方法的设计与实现。
堆 其实是一种完全二叉树,这个结构明显的好处是可以用数组来表示,不用指针来表示,这样我们可以省去很多不必要的麻烦。这里最大堆和最小堆的概念可以查看严蔚敏的数据结构神书。堆排序的过程大家可以再百度上寻找,这里也不详细介绍。
然后说一下优先队列,需要如下集中关键的操作。
(1)push() :将元素插入到优先队列。
(2)top():返回优先级最高的元素.
(3) pop():弹出优先级最高的元素。
(4)increase():将某一个元素的优先级提升到某个数。
top()函数只要返回数组的第一个元素就可以了,期就为最大值, pop函数主要功能是弹出最大的元素,让数组的第一个元素与最后一个元素交换一下,然后将数组的长度减1,然后调整堆就可以了, increase函数将A[i]的设为指定的优先级。然后在i>1且A[i]的父节点一直小于A[i]的情况下,一直做两件事:a.交换A[i]与它的父节点的值。b.将i递增为父节点的序号。
具体的实现代码
#include<stdio.h> #include<stdlib.h> #include<malloc.h> typedef struct List { int *data; int length; int size; }*pArrayList; void heapAdjust(pArrayList list,int index,int length) { int lchild=index*2+1; int rchild=index*2+2; int largest; if(lchild<=length && list->data[lchild]>list->data[index]) { largest=lchild; } else largest=index; if(rchild<=length && list->data[rchild]>list->data[largest]) { largest=rchild; } if(largest!=index) { int tmp=list->data[index]; list->data[index]=list->data[largest]; list->data[largest]=tmp; heapAdjust(list,largest,length); } } void BuildMaxHeap(pArrayList list) { for(int i=(list->length-2)/2;i>=0;i--) { heapAdjust(list,i,list->length); } } void printArrayList(pArrayList list) { for(int i=0;i<list->length;i++) { printf("%d ",list->data[i]); } printf("\n"); } void heapSort(pArrayList list) { BuildMaxHeap(list); printf("构成最大堆:"); printArrayList(list); int len=list->length-1; for(int i=list->length-1;i>0;--i) { int tmp=list->data[0]; list->data[0]=list->data[i]; list->data[i]=tmp; printf("交换以后:"); printArrayList(list); --len; heapAdjust(list,0,len); } printf("最终结果:"); printArrayList(list); } int top(pArrayList list) { return list->data[0]; } int pop(pArrayList list) { int head=list->data[0]; list->data[0]=list->data[list->length-1]; --list->length; heapAdjust(list,0,list->length); return head; } int max(int a,int b) { return a>b?a:b; } void decreaseKey(pArrayList list,int index,int key) { if(list->data[index]<key) { printf("new key must be smaller"); return ; } else { list->data[index]=key; } int tmp; while(index<list->length&& max(list->data[index*2+1],list->data[index*2+2])>list->data[index]) { int itmp; tmp=list->data[index]; list->data[index]=max(list->data[index*2+1],list->data[index*2+2]); if(list->data[index*2+1]==max(list->data[index*2+1],list->data[index*2+2])) { itmp=index*2+1; } else { itmp=index*2+2; } list->data[itmp]=tmp; index=itmp; } } void increaseKey(pArrayList list,int index ,int key) { if(list->data[index]>key) { printf("new Key must be bigger "); return ; } else { list->data[index]=key; } int tmp; while(index>0 && list->data[(index-2)/2]<list->data[index]) { tmp=list->data[index]; list->data[index]=list->data[(index-2)/2]; list->data[(index-2)/2]=tmp; index=(index-2) / 2; } } void push(pArrayList list, int key) { if(list->length==list->size) { list->data=(int *)realloc(list->data,sizeof(int) * list->size * 2); list->size=list->size*2; } list->data[list->length]=-1; increaseKey(list,list->length,key); ++list->length; BuildMaxHeap(list); } void main() { pArrayList list; list=(pArrayList)malloc(sizeof(List)); list->data=(int *)malloc(sizeof(int)*5); for(int i=0;i<5;i++) { list->data[i]=i; } list->length=5; list->size=5; BuildMaxHeap(list); //increaseKey(list,3,7); decreaseKey(list,0,1); //push(list,8); //BuildMaxHeap(list); printArrayList(list); printf("%d\n",top(list)); }