[算法学习笔记]基于最大堆实现最大优先队列
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; }
相关文章推荐
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- C#递归算法之分而治之策略
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- C#算法之大牛生小牛的问题高效解决方法
- C#算法函数:获取一个字符串中的最大长度的数字
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- 经典排序算法之冒泡排序(Bubble sort)代码
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法