【C++】大根堆與小根堆


STL實現

C++中,大根堆和小根堆可以使用優先隊列實現。

#include <queue>
priority_queue<int> pq1 // 大根堆
priority_queue<int, vector<int>, greater<int>> pq2 // 小根堆

該STL支持自定義比較函數,但與sort不同,不支持直接使用lambda函數。自定義的小根堆如下。

struct cmp {bool operator()(int a,int b) {return a > b;}}; // 自定義小根堆
priority_queue<int, vector<int>, cmp> pq;

更加復雜的自定義函數可以參照【LeetCode-1792】最大平均通過率

手寫

大小根堆的前備知識為堆排序,具體是使用堆排序中的節點上浮(swim)和下沉(sink)實現。整體的數據結構可以使用vectorpush新的數值時,將其放在數組最后,然后與對應位置的父節點比較,進行上浮操作;pop堆頂數值時,將該節點與隊尾數字交換,然后移除隊尾數字,並對當前交換后的堆頂元素進行下沉操作。具體代碼如下。

vector<int> pq{0}; // 首位填充一個數值,方便找根節點與子節點
void insert(int num) {
    pq.push_back(num);
    swim(pq.size() - 1);
}
int popTop() {
    swap(pq[1], pq.back());
    int res = pq.back();
    pq.pop_back();
    sink(1);
    return res;
}
int peekTop() {
    return pq[1];
}
bool isPrior(int i, int j) { // 自定義函數部分,此處實現的是大根堆
    return pq[i] > pq[j];
}
void swim(int i) { // 子節點與父節點比較
    while (i > 1 && isPrior(i, i / 2)) {
        swap(pq[i], pq[i / 2]);
        i /= 2;
    }
}
void sink(int i) { // 父節點與左右節點中最大的進行比較
    int n = pq.size();
    while (i * 2 < n) {
        int j = i * 2;
        if (j + 1 < n && isPrior(j + 1, j)) j++;
        if (isPrior(i , j)) break;
        swap(pq[i], pq[j]);
        i = j;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM