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

何为优先队列

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

优先队列分为最大优先队列和最小优先队列, 本文实现的是最大优先队列.
优先队列会让优先级最高的元素优先出来.
和堆排序一样,最大优先队列也是基于最大堆来实现的. 一个优先队列实现以下几个操作:

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;
}
  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值