W. :最大优先级队列

//author: W.
//最大优先级队列,P80.
//一个最大优先级队列包含以下几个操作
//INSERT(S, x) :把元素x插入集合S. 时间复杂度O(lgn)
//MAXIMUM(S):返回S中具有最大关键字的元素.时间复杂度O(1)
//EXTRACT-MAX(S):去掉并返回S中的具有最大关键字的元素.时间复杂度O(lgn)
//INCREASE-KEY(S, x, k):将元素x的关键字的值增加到k,这里k值不能小于x的原关键字的值.时间复杂度O(lgn)
//可见优先级队列操作的任意操作可在O(lgn)时间内完成。

#include <stdio.h>
#include <stdlib.h>

//对于优先级序列中存储的数据,书中描述“需要在对中的每个元素里存储对应的应用对象的柄。同样的,我们需要将堆中元素的柄存储到其对应的应用对象中”
//这里对象的柄通过对象的指针表示,堆中元素的柄通过元素的索引号表示
typedef struct{
    int key;
    int heap_index;
    int data;
} Data;

typedef Data* PData;
#define NULLPDATA NULL

PData HEAP_MAXIMUM(const PData A[], const int heap_size)
{
    if(heap_size < 1)
    {
        return NULLPDATA;
    }
    return A[0];
}

void ElemCopy(PData A[], int dest_index, int src_index)
{
    A[dest_index] = A[src_index];
    A[dest_index]->heap_index = dest_index;
}

void ElemSwap(PData A[], int index1, int index2)
{
    PData temp;
    temp = A[index1];
    A[index1] = A[index2];
    A[index2] = temp;
    A[index1]->heap_index = index1;
    A[index2]->heap_index = index2;
}

void MaxHeapify(PData A[], const int length, int i)
{
    int left = 2 * i + 1;  //见P71,注意书上是根从1开始计数的,而程序中的数组下标是从0开始计数的
    int right = 2 * i + 2;
    int largest = i;
    if((left <= length-1) && (A[left]->key > A[largest]->key))
    {
        largest = left;
    }
    if((right <= length-1) && (A[right]->key > A[largest]->key))
    {
        largest = right;
    }
    if(largest != i)
    {
        ElemSwap(A, i, largest);
        MaxHeapify(A, length, largest);
    }
}

PData HEAP_EXTRACT_MAX(PData A[], int* pheap_size)
{
    if(*pheap_size < 1)
    {
        return NULLPDATA;
    }
    PData max = A[0];
    ElemCopy(A, 0, *pheap_size-1);
    --(*pheap_size);
    MaxHeapify(A, *pheap_size, 0);
    return max;
}

void HEAP_INCREASE_KEY(PData A[], int index, int key)
{
    if(key < A[index]->key)
    {
        return ;//更新的key必须大于等于原key。(key表示优先级)
    }
    A[index]->key = key;
    while((index > 0) && (A[(index-1)/2]->key < A[index]->key))    //index的父结点的下标为(i-1)/2,见P71,注意书上是根从1开始计数的,而程序中的数组下标是从0开始计数的
    {
        ElemSwap(A, index, (index-1)/2);
        index = (index-1)/2;
    }
}

void MAX_HEAP_INSERT(PData A[], int* pheap_size, PData newdata)
{
    ++(*pheap_size);
    A[*pheap_size-1] = newdata;
    HEAP_INCREASE_KEY(A, *pheap_size-1, A[*pheap_size-1]->key);
}

void increase_key(PData A[], PData pdata, int newkey)
{
    HEAP_INCREASE_KEY(A, pdata->heap_index, newkey);
}

void test_MaxPriorityQueue()
{
    int i;
    Data data_array[10];
    for(i = 0; i < 10; ++i)
    {
        data_array[i].data = i * 100;
    }
    data_array[0].key = 1;
    data_array[1].key = 7;
    data_array[2].key = 10;
    data_array[3].key = 8;
    data_array[4].key = 9;
    data_array[5].key = 3;
    data_array[6].key = 16;
    data_array[7].key = 2;
    data_array[8].key = 4;
    data_array[9].key = 14;
    //用一个存储PData的数组来作为优先级序列,这里忽略掉数组的增长问题,即假设数组不存在越界的情况。
    PData S[100];
    int S_heap_size = 0;
   
    for(i = 0; i < 10; ++i)
    {
        MAX_HEAP_INSERT(S, &S_heap_size, &data_array[i]);
    }
 
    PData maxdata = HEAP_MAXIMUM(S, S_heap_size);
    printf("The max key is %d, data = %d/n", maxdata->key, maxdata->data);
    for(i = 0; i < 10; ++i)
    {
        PData pdata;
        pdata = HEAP_EXTRACT_MAX(S, &S_heap_size);
        printf("i = %d, key = %d, data = %d/n", i, pdata->key, pdata->data);
    }
    if(HEAP_MAXIMUM(S, S_heap_size) == NULLPDATA)
    {
        printf("current S is NULL/n");
    }
   
    for(i = 0; i < 10; ++i)
    {
        MAX_HEAP_INSERT(S, &S_heap_size, &data_array[i]);
    }
    increase_key(S, &data_array[8], 15);
    printf("/n将原key为4的元素的key提升为15/n"); //见P82示例

    for(i = 0; i < 10; ++i)
    {
        PData pdata;
        pdata = HEAP_EXTRACT_MAX(S, &S_heap_size);
        printf("i = %d, key = %d, data = %d/n", i, pdata->key, pdata->data);
    }
}

int main(int argc, char** argv)
{
    test_MaxPriorityQueue();
    return 0;
}

//输出:
//The max key is 16, data = 600
//i = 0, key = 16, data = 600
//i = 1, key = 14, data = 900
//i = 2, key = 10, data = 200
//i = 3, key = 9, data = 400
//i = 4, key = 8, data = 300
//i = 5, key = 7, data = 100
//i = 6, key = 4, data = 800
//i = 7, key = 3, data = 500
//i = 8, key = 2, data = 700
//i = 9, key = 1, data = 0
//current S is NULL
//
//将原key为4的元素的key提升为15
//i = 0, key = 16, data = 600
//i = 1, key = 15, data = 800
//i = 2, key = 14, data = 900
//i = 3, key = 10, data = 200
//i = 4, key = 9, data = 400
//i = 5, key = 8, data = 300
//i = 6, key = 7, data = 100
//i = 7, key = 3, data = 500
//i = 8, key = 2, data = 700
//i = 9, key = 1, data = 0

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值