堆的应用——优先级队列的实现

优先级队列

队列遵循先进先出原则,无优先级。
优先级队列则不同,每个数都有优先级,我们假设最大的数具有高优先级,则在一个有一堆数据的优先级队列中,每次出数据出优先级最高的那个数据,也就是每次出数据最大的那个数。
例:
优先级队列

优先级队列的实现

优先级队列可以通过一个有序数组实现,但是时间复杂度过高,每次有新的数据入队列就需要重新排序,比较慢。
用堆实现可以将时间复杂度优化到每次入数据在时间复杂度上只需要 log2n log 2 ⁡ n ,可以说是一个非常快的算法了,而且实现起来也不是很复杂,只需要把堆的结构稍加修改就能当作优先级队列使用。
如果需要大的数据优先出队列则建大堆,小数据优先出队列就建小堆,每次有新的数据入队就根据堆的特性向上调整,有数据出队列就向下调整。
优先级队列

入一个100进入队列
优先级队列

在没有入100之前,将87出队列
优先级队列

看到这,大家可能大概能知道优先级队列的实现了,无非是将堆换个名字来改叫优先级队列,其思想就是堆的思想,下面通过代码实现

实现代码(戳此下载)

代码从增删查改四个常规的功能实现

运行结果

运行结果

代码

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

#define _SIZE 5

typedef int PQueueDataType;

typedef struct PriorityQueue
{
    int* _a;
    int _size;
    int _capacity;
}PQueue;

PQueue* PQueueInit();//初始化优先级队列
void PQueuePush(PQueue* q, PQueueDataType data);//入队
void PQueueAdjustUp(PQueue* q, int child);//数据向上调整
void PQueueAdjustDown(PQueue* q, int parent);//数据向下调整
void PQueuePop(PQueue* q);//出队列
PQueueDataType PQueueTop(PQueue* q);//获取队列头数据
void PQueueDestroy(PQueue* q);//队列销毁

void TestPQueue();//测试用例

PQueue* PQueueInit()
{
    PQueue* q = (PQueue*)malloc(sizeof(PQueue));
    q->_capacity = _SIZE;
    q->_size = 0;
    q->_a = (PQueueDataType*)malloc(sizeof(PQueueDataType) * q->_capacity);
    return q;
}

void PQueueCheckCapacity(PQueue* q)
{
    assert(q);
    if (q->_size == q->_capacity)
    {
        q->_capacity *= 2;
        q->_a = realloc(q->_a, sizeof(PQueueDataType) * q->_capacity);
        assert(q->_a);
    }
}

void PQueueSwap(PQueueDataType* data1, PQueueDataType* data2)
{
    assert(data1 && data2);
    *(data1) ^= *(data2);
    *(data2) ^= *(data1);
    *(data1) ^= *(data2);
}

void PQueueAdjustUp(PQueue* q, int child)
{
    assert(q);
    PQueueDataType parent = (child - 1) / 2;
    while (child)
    {
        if (*(q->_a + parent) < *(q->_a + child))
        {
            PQueueSwap(q->_a + parent, q->_a + child);
            child = parent;
            parent = (child - 1) / 2;
        }
        else
        {
            break;
        }
    }
}

void PQueueAdjustDown(PQueue* q, int parent)
{
    assert(q);
    int child = parent * 2 + 1;
    while (child < q->_size)
    {
        if (child + 1 < q->_size)
        {
            if (*(q->_a + child) < *(q->_a + child + 1))
            {
                child += 1;
            }
        }
        if (*(q->_a + parent) < *(q->_a + child))
        {
            PQueueSwap(q->_a + parent, q->_a + child);
            parent = child;
            child = parent * 2 + 1;
        }
        else
        {
            break;
        }
    }
}

void PQueuePush(PQueue* q, PQueueDataType data)
{
    assert(q);
    PQueueCheckCapacity(q);
    *(q->_a + q->_size) = data;
    q->_size++;
    PQueueAdjustUp(q, q->_size - 1);
}

void PQueuePop(PQueue* q)
{
    assert(q);
    *(q->_a + 0) = *(q->_a + q->_size - 1);
    q->_size--;
    PQueueAdjustDown(q, 0);
}

PQueueDataType PQueueTop(PQueue* q)
{
    assert(q && (q->_size > 0));
    return *(q->_a + 0);
}

void PQueueDestroy(PQueue* q)
{
    assert(q);
    free(q->_a);
    free(q);
}

void TestPQueue()
{
    PQueueDataType arr[] = { 53,17,78,9,45,65,87,23,31 };
    PQueue* pq = PQueueInit();
    printf("入队列测试:");
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        PQueuePush(pq, arr[i]);
    }
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", *(pq->_a + i));
    }
    printf("\n");
    printf("出队列测试:");
    for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
    {
        printf("%d ", PQueueTop(pq));
        PQueuePop(pq);
    }
    printf("\n");
    PQueueDestroy(pq);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值