📜  最小堆优先级队列 c++ (1)

📅  最后修改于: 2023-12-03 15:40:16.313000             🧑  作者: Mango

最小堆优先级队列 C++ 介绍

最小堆优先级队列是一种非常常见的数据结构,它可以在 $O(logn)$ 的时间内实现 push 和 pop 操作。在 C++ 中,STL 的 priority_queue 就是基于最大堆实现的优先级队列,而最小堆优先级队列则需要手动实现。

最小堆的实现

最小堆是一种二叉树数据结构,它的每个节点的父节点都要小于或等于它的子节点。可以使用数组来实现最小堆,我们假设数组下标是从 1 开始的,那么节点 i 的左子节点就是 $2i$,右子节点就是 $2i+1$,父节点就是 $\lfloor i/2 \rfloor$。

现在来看一下如何实现一个最小堆。在 C++ 中,我们可以使用一个 vector 数组来存储堆中的元素。由于 vector 的下标从 0 开始,所以可以使用一个小技巧,将堆中的元素下标从 1 开始,而 0 号位置留空。这样就可以直接使用公式计算节点的左右子节点和父节点了。

class MinHeap {
public:
    MinHeap() {}
    
    // 向堆中插入一个元素
    void push(int val) {
        heap.push_back(val);
        int cur = size();
        while (cur > 1) {
            int parent = cur / 2;
            if (heap[parent] > heap[cur]) {
                swap(heap[parent], heap[cur]);
                cur = parent;
            } else {
                break;
            }
        }
    }
    
    // 从堆中取出并删除最小元素
    int pop() {
        int res = heap[1];
        heap[1] = heap.back();
        heap.pop_back();
        int cur = 1;
        while (cur * 2 < size()) {
            int child = cur * 2;
            if (child + 1 < size() && heap[child + 1] < heap[child]) {
                child++;
            }
            if (heap[child] < heap[cur]) {
                swap(heap[cur], heap[child]);
                cur = child;
            } else {
                break;
            }
        }
        return res;
    }

    // 获取堆中最小元素
    int top() const {
        return heap[1];
    }

    // 判断堆是否为空
    bool empty() const {
        return size() == 0;
    }

    // 获取堆的大小
    int size() const {
        return heap.size() - 1;
    }

private:
    vector<int> heap;
};

以上就是最小堆的实现代码,可以通过 push、pop、top、empty 和 size 函数来操作最小堆。

最小堆优先级队列的实现

有了最小堆,我们就可以通过它来实现最小堆优先级队列。最小堆优先级队列可以使用两个堆来实现,一个是存储元素的堆,另一个是存储元素的优先级的堆。其中,第一个堆按照元素大小排序,第二个堆按照元素的优先级排序,排序方式和最小堆相反,即优先级最大的元素排在堆顶。

下面是最小堆优先级队列的实现代码:

struct Node {
    int val; // 元素值
    int priority; // 优先级
    Node(int val, int priority) : val(val), priority(priority) {}
    bool operator<(const Node& other) const {
        return priority > other.priority;
    }
};

class MinHeapPriorityQueue {
public:
    MinHeapPriorityQueue() {}

    // 向队列中插入一个元素
    void push(int val, int priority) {
        heap.push(Node(val, priority));
    }

    // 从队列中取出并删除优先级最高的元素
    int pop() {
        int res = heap.top().val;
        heap.pop();
        return res;
    }

    // 判断队列是否为空
    bool empty() const {
        return heap.empty();
    }

private:
    priority_queue<Node> heap; // 存放元素的优先级堆
};
总结

最小堆优先级队列是一种非常实用的数据结构,它可以帮助我们在处理一些需要按照优先级排序的元素时,快速地取出优先级最高的元素。在 C++ 中,STL 的 priority_queue 是最大堆优先级队列,我们可以通过手动实现最小堆来实现最小堆优先级队列。