手写优先级队列

文章目录


#include <iostream>
using namespace std;

// 基于max-heaps大顶堆,key表示
class PriorityQueue
{
public:
    // 返回最大key值的元素,即队首
    int MAXIMUM();

    // 弹出队首并返回队首
    int EXTRACT_MAX();

    // 增加(赋值)堆中下标为i的key
    void INCREASE_KEY(int i, int key);

    // 插入元素
    bool INSERT(int key);

    // 初始化数组大小
    PriorityQueue(int max_size)
    {
        this->max_size = max_size;
        this->A = new int[max_size];
    }

    // 删除分配的数组
    ~PriorityQueue()
    {
        delete[] this->A;
        this->A = NULL;
    }

private:
    // 初始化于BUILD_MAX_HEAP(),用于MAX_HEAPIFY()中
    int heap_size = 0;

    // 堆的最大容量
    int max_size = -1;

    // 用数组存储的堆
    int *A = NULL;

    // 最大值
    int INF = 0x3F3F3F3F;

    int LEFT(int i);

    int RIGHT(int i);

    int PARENT(int i);

    // 调整本结点以下的顶堆为大顶堆
    void MAX_HEAPIFY(int A[], int i);
};

int PriorityQueue::LEFT(int i)
{
    // 伪代码是2 * i
    return 2 * i + 1;
}

int PriorityQueue::RIGHT(int i)
{
    // 伪代码是2 * i + 1
    return 2 * (i + 1);
}

int PriorityQueue::PARENT(int i)
{
    // 伪代码是PARENT(i)=⌊i/2⌋
    return (int)((i + 1) / 2) - 1;
    // 或者 return floor((i + 1) / 2) - 1; 需要 #include <math.h> // for floor()
}

// 调整本结点以下的顶堆为大顶堆
void PriorityQueue::MAX_HEAPIFY(int A[], int i)
{
    // 获得左孩子下标
    int l = this->LEFT(i);
    // 获得右孩子下标
    int r = this->RIGHT(i);

    /* 比较本节点、左子节点、右子节点的值,让largest为最大下标 */

    // 本结点、左孩子、右孩子中值最大的结点下标。先假设本结点最大
    int largest = i;
    // 检验l是否没有越界,并且当左孩子的值比本结点的更大时
    if (l < this->heap_size && A[l] > A[i])
    {
        // 则最大值的下标largest为左孩子的下标l
        largest = l;
    }

    // 检验r是否没有越界,并且当右孩子的值比最大值结点的更大时
    if (r < this->heap_size && A[r] > A[largest])
    {
        // 则最大值的下标largest为右孩子的下标r
        largest = r;
    }

    // 当最大值的下标不是本结点i时(需要调整因交换而破坏的下一层大顶堆)时
    if (largest != i)
    {
        // 则交换本结点A[i]和最大值结点的值A[largest]
        swap(A[i], A[largest]);
        // 对最大值结点的大顶堆进行调整
        MAX_HEAPIFY(A, largest);
    }
}

// 返回最大key值的元素,即队首
int PriorityQueue::MAXIMUM()
{
    // 返回队首
    return A[0];
}

// 返回队首并弹出队首
int PriorityQueue::EXTRACT_MAX()
{
    // 弹出不合法
    if (this->heap_size < 1)
    {
        return -1;
    }

    // 最大值是队首
    int max = A[0];
    // 交换队首(根节点)和队尾(最后一个叶子结点)
    A[0] = A[this->heap_size - 1];
    // 弹出队首后数量减一
    this->heap_size--;
    // 对树根进行MAX-HEAPIFY,因为交换了树根A和最后的叶子结点
    this->MAX_HEAPIFY(A, 0);
    // 返回最大值(弹出的队首)
    return max;
}

// 增加(赋值)堆中下标为i的key
void PriorityQueue::INCREASE_KEY(int i, int key)
{
    // 增加下标i的key
    A[i] = key;

    // 不断调整该结点和该结点的父结点,直到为根结点或者不用调整父子结点
    while (i > 0 && A[this->PARENT(i) < A[i]])
    {
        // 交换
        swap(A[i], A[this->PARENT(i)]);
        // 更新i,继续向上层调整
        i = this->PARENT(i);
    }
}

// 插入元素
bool PriorityQueue::INSERT(int key)
{
    // 超堆容量检查
    if (this->heap_size < this->max_size)
    {
        // 插入新的数据自然数量加一
        this->heap_size++;
    }
    else
    {
        return false;
    }
    // 赋予新插入的值权值key
    this->INCREASE_KEY(this->heap_size - 1, key);
    return true;
}

int main()
{
    // 取10个最大容量
    PriorityQueue priorityQueue(10);
    // 插入key为1
    priorityQueue.INSERT(1);
    cout << priorityQueue.MAXIMUM() << endl;
    // 1
    // 插入key为3
    priorityQueue.INSERT(3);
    // 3
    cout << priorityQueue.MAXIMUM() << endl;
    // 修改下标为1的数据的key为4
    priorityQueue.INCREASE_KEY(1, 4);
    // 返回并弹出
    cout << priorityQueue.EXTRACT_MAX() << endl;
    // 4
    cout << priorityQueue.EXTRACT_MAX() << endl;
    // 3
    cout << priorityQueue.EXTRACT_MAX() << endl;
    // -1.表示优先级队列空了
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值