【C++】自定义实现 priority_queue——用 vector、堆实现(code c++)

目录&索引

  • 堆原理简介
  • 程序代码
    • 自定义实现 priority_queue——用 vector、堆实现 code c++
    • 运行结果
  • 结论


堆原理简介

堆是一种特殊的树结构,即完全二叉树。堆分为大顶堆和小顶堆,大顶堆为根节点的值大于两个子节点的值;小顶堆为根节点的值小于两个子节点的值,同时根节点的两个子树也分别是一个堆。

通俗来讲,二叉树在按层序遍历时在遇到第一个 nullptr 指针即作为结尾的二叉树就可以称之为完全二叉树。
【C++】自定义实现 priority_queue——用 vector、堆实现(code c++)_第1张图片
假设根节点下标为 0,若父节点相应数组下标为 i,则其左孩子相应数组下标为 2i+1,右孩子为 2i+2。

注意:如果我们现在处理第 i 个序号的结点的数,那么他的父结点序号就是 (i-1)/2;它的孩子结点就为 2i+1 与 2i+2,反推 2i+1-1 和 2i+2-1 除以 2 可以得到 i。当前 n 个节点的堆,根节点从 0 开始,则最后一个叶节点的下标为 n-1,其父节点是第一个非叶节点,下标为 ((n-1)-1)/2 = n/2-1。


程序代码

自定义实现 priority_queue——用 vector、堆实现 code c++

#include 
#include 
#include 
#include 
#include 
using namespace std;

class IQueue { // 实现 priority_queue, 接口定义
public :
    virtual void push(int) = 0;
    virtual void pop() = 0;
    virtual bool empty() = 0;
    virtual int top() = 0;
    virtual int size() = 0;
};

class vector_queue : public IQueue, public vector<int> { // 用 vector 实现
public :
    void push(int x) override {
        this->vector<int>::push_back(x);
        return ;
    } 
    void pop() override {
        if (this->vector<int>::empty()) return ;
        vector<int>::iterator p = this->begin();
        for (auto iter = begin(); iter != end(); ++iter) {
            if (*iter > *p) p = iter;
        }
        this->vector<int>::erase(p);
        return ;
    }
    bool empty() override {
        return this->size() == 0;
    }
    int top() override {
        if (this->empty()) return 0;
        int ans = at(0);
        for (int i = 1; i < size(); ++i) {
            ans = max(at(i), ans); 
        }
        return ans;
    }
    int size() override {
        return this->vector<int>::size();
    }
};

class heap_queue : public IQueue, public vector<int> { // 用堆实现
public :
    void push(int x) override {
        push_back(x);
        up_maintain(size());
        return ;
    } 
    void pop() override {
        std::swap(at(0), at(size() - 1));
        pop_back();
        down_maintain(1);
        return ;
    }
    bool empty() override {
        return size() == 0;
    }
    int top() override {
        if (empty()) return 0;
        return at(0);
    }
    int size() override {
        return this->vector<int>::size();
    }
private:
    void up_maintain(int ind) {
        while (ind > 1 && at(ind - 1) > at((ind / 2) - 1)) {
            std::swap(at(ind - 1), at((ind / 2) - 1));
            ind /= 2;
        }
        return ;
    }
    void down_maintain(int ind) {
        int temp = ind;
        while (ind * 2 <= size()) {
            int temp = ind;
            if (at(ind * 2 - 1) > at(temp - 1)) temp = ind * 2;
            if (ind * 2 + 1 <= size() && at(ind * 2) > at(temp - 1)) temp = ind * 2 + 1;
            if (temp == ind) break;
            std::swap(at(temp - 1), at(ind - 1));
            ind = temp;
        }
        return ;
    }
};

void quick_sort(int *arr, int l, int r) { // 快排
    if (l >= r) return ;
    int x = l, y = r, z = arr[(l + r) >> 1];
    do {
        while (arr[x] < z) ++x;
        while (arr[y] > z) --y;
        if (x <= y) {
            swap(arr[x], arr[y]);
            ++x, --y;
        }
    } while (x <= y);
    quick_sort(arr, x, r);
    quick_sort(arr, l, y);
    return ;
}

int main() {
    // 快排测试
    int arr[10] = {1, 5, 9, 6, 8, 7, 4, 3, 2, 13};
    quick_sort(arr, 0, 9);
    for (int i = 0; i < 10; ++i) {
        cout << arr[i] << " ";
    }
    cout << endl;
    // 自定义 priority_queue 测试
    srand(time(0));
    vector_queue q1;
    heap_queue q2;
    for (int i = 0; i < 10; ++i) {
        int val = rand() % 100;
        q1.push(val);
        cout << "push q1 : " << val << endl;
    }
    while (!q1.empty()) {
        cout << q1.top() << " ";
        q1.pop();
    }
    cout << endl;
    for (int i = 0; i < 10; ++i) {
        int val = rand() % 100;
        q2.push(val);
        cout << "push q2 : " << val << endl;
    }
    while (!q2.empty()) {
        cout << q2.top() << " ";
        q2.pop();
    }
    cout << endl;
    return 0;
}

运行结果

1 2 3 4 5 6 7 8 9 13 
push q1 : 13
push q1 : 17
push q1 : 83
push q1 : 36
push q1 : 60
push q1 : 11
push q1 : 58
push q1 : 38
push q1 : 11
push q1 : 17
83 60 58 38 36 17 17 13 11 11 
push q2 : 35
push q2 : 94
push q2 : 98
push q2 : 60
push q2 : 59
push q2 : 21
push q2 : 98
push q2 : 72
push q2 : 18
push q2 : 16
98 98 94 72 60 59 35 21 18 16 

结论

代码示例,有问题留言。


你可能感兴趣的:(C++,c++,stl,堆排序,快速排序)