您的位置:首页 > 其它

[算法学习笔记]基于最大堆实现最大优先队列

2016-07-24 11:56 573 查看

何为优先队列

优先队列是计算机科学中的一类抽象数据类型。优先队列中的每个元素都有各自的优先级,优先级最高的元素最先得到服务;优先级相同的元素按照其在优先队列中的顺序得到服务。优先队列往往用堆来实现。

优先队列分为最大优先队列和最小优先队列, 本文实现的是最大优先队列.

优先队列会让优先级最高的元素优先出来.

和堆排序一样,最大优先队列也是基于最大堆来实现的. 一个优先队列实现以下几个操作:

int heapMaximum(int []);                    // 返回最大元素
int heapExtractMax(int []);                 // 返回病删去最大元素
int maxHeapInsert(int [], int);            // 插入元素
int heapIncreaseKey(int [], int, int);     // 将元素x的关键字增加到k


heapMaximun操作

int heapMaximum(int A[]){
if(heapSize == 0)
return -INF;
return A[1];
}


该操作会返回优先级最高的元素, 在最大堆中, 最大的元素就是根节点, 即数组中的第一个元素. 这里有如果当前的最大堆为空就返回-INF, 其实在这里抛出一个异常的写法更好, 不过c语言没有自带处理异常的功能, 所以就用了这种不太好的写法

heapExtractMax操作

int heapExtractMax(int A[]){
if(heapSize == 0)
return -INF;
int max= A[1];
A[1] = A[heapSize];
heapSize--;
if(heapSize > 1)
maxHeapify(A, 1);
return max;
}


该操作实现了去掉并返回优先级最高的元素.

该操作和堆排序中的heapSort函数有相似之处, 都是将根节点和最后一个元素进行交换, 然后领heapSize自减, 再利用maxHeapify维护最大堆的性质, maxHeapify操作在上一篇文章里有介绍.

maxHeapInsert操作

int maxHeapInsert(int A[], int key){
if(heapSize == MAX_N)
return -INF;
heapSize++;
A[heapSize] = -INF;
int res = heapIncreaseKey(A, heapSize, key);
return res;
}


该操作实现插入数据的功能

heapIncreaseKey操作

int heapIncreaseKey(int A[], int i, int key){
if(key < A[i])
return -INF;
A[i] = key;
while(i > 1 && A[PARENT(i)] < A[i]){
swap(A+i, &A[PARENT(i)]);
i = PARENT(i);
}

return OK;
}


该操作实现了上一个操作

c语言完整代码

#include <stdio.h>

#define MAX_N 10
#define INF 1000010
#define OK 1
#define PARENT(i) i >> 1
#define LEFT(i) i << 1
#define RIGHT(i) (i << 1) + 1

int heapSize;

void swap(int *, int *);
void maxHeapify(int [], int); // 维护二叉堆的性质
int heapMaximum(int []); // 返回最大元素 int heapExtractMax(int []); // 返回病删去最大元素 int maxHeapInsert(int [], int); // 插入元素 int heapIncreaseKey(int [], int, int); // 将元素x的关键字增加到k

int main(){
int A[MAX_N+1], choose;
int key, max, i;
heapSize = 0;
printf("menu: 1> push 2> getMax 3> pop 0> eixt\nInput: ");
while(scanf("%d", &choose) && choose){
switch (choose ) {
case 1:
printf("Input: ");
scanf("%d", &key);
if(maxHeapInsert(A, key) == -INF){
printf("Output: Insert fail! Queue is full!\n");
}
printf("Output: ");
for(i = 1; i <= heapSize; i++){
printf("%d\t", A[i]);
}
printf("\n");
break;
case 2:
max = heapMaximum(A);
if(max == -INF)
printf("Output: Error! Queue is empty!\n");
else
printf("Output: %d\n", max);
break;
case 3:
max = heapExtractMax(A);
if(max == -INF)
printf("Output: Error! Queue is empty!\n");
else
printf("Output: %d is pop!\n", max);
break;
default:
printf("Output: error choose\n");
break;
}
printf("Input: ");
}
printf("Output: Done!\n");

return 0;
}

void swap(int *a, int *b){
int temp = *a;
*a = *b;
*b = temp;
}

void maxHeapify(int A[], int i){
int l = LEFT(i);
int r = RIGHT(i);
int largest;
if(l <= heapSize && A[i] < A[l])
largest = l;
else
largest = i;
if(r <= heapSize && A[largest] < A[r])
largest = r;
if(largest != i){
swap(A + i, A + largest);
maxHeapify(A, largest);
}
}

int heapMaximum(int A[]){ if(heapSize == 0) return -INF; return A[1]; }

int heapExtractMax(int A[]){ if(heapSize == 0) return -INF; int max= A[1]; A[1] = A[heapSize]; heapSize--; if(heapSize > 1) maxHeapify(A, 1); return max; }

int maxHeapInsert(int A[], int key){ if(heapSize == MAX_N) return -INF; heapSize++; A[heapSize] = -INF; int res = heapIncreaseKey(A, heapSize, key); return res; }

int heapIncreaseKey(int A[], int i, int key){ if(key < A[i]) return -INF; A[i] = key; while(i > 1 && A[PARENT(i)] < A[i]){ swap(A+i, &A[PARENT(i)]); i = PARENT(i); } return OK; }
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  算法