c++优先队列 priority_queue 二叉堆 最大堆实现

本文介绍了C++标准库中的优先队列`std::priority_queue`的使用,包括最大堆和最小堆的初始化。接着,详细讲解了二叉最大堆的实现原理,强调了其数组存储和节点位置的关系。最后,给出了一个自定义的`priority_queue`最大堆模板类的实现,包括插入、删除和调整堆的方法,并通过示例展示了其用法。


前言

c11 stl中提供优先队列的数据结构,可以实现最大堆和最小堆

一、priority_queue使用方式

1.初始化方式

std::prioriry_queue<int> tmp; //默认最大堆
std::priority_queue<int, vector<int>, std::greater<int>> tmp; //最小堆定义方式

2.成员函数

在这里插入图片描述

二、 二叉最大堆的实现原理

  1. 二叉堆底层采用数组实现,排列紧凑的数组
  2. 由于上述特点,所以二叉堆中父节点位置是 (i - 1)/2,左子节点位置是 2i + 1 右子节点位置是 2i + 2
  3. 插入一个新元素,新元素需要与父节点比较,如果比父节点大,需要上移
  4. 删除堆顶最大元素时,需要将堆尾的元素放到堆顶上,然后与左右子节点比较,如果比左右子节点中最大的小,需要下移

参考 二叉堆的实现

三、自己实现的priority_queue 最大堆代码

#include <iostream>
#include <vector>
using namespace std;

/*========================
简易priority_queue实现,只实现了最大堆
========================*/
// 由于二叉堆的特性
// 二叉堆中父节点位置是 (i - 1)/2
// 左子节点位置是 2*i + 1  右子节点位置是 2*i + 2

template <class T>
class priority_queue {
   
   
private:
    // 二叉堆底层采用数组存放
    vector<T> heap_;
private:
    // 堆尾插入一个新值后,需要向上调整堆
    void 
C++中使用`priority_queue`包含自定义结构体时,需要定义结构体的比较规则。由于`priority_queue`默认使用元素的比较函数来确定元素的优先级顺序,因此对于自定义结构体,需要手动提供比较函数。下面详细介绍两种常用的实现方法: ### 使用仿函数(Functor) 仿函数是一个重载了`()`运算符的类或结构体,它的对象可以像函数一样调用。在`priority_queue`中使用仿函数可以定义自定义结构体的比较规则。 以下是一个示例代码: ```cpp #include <iostream> #include <queue> // 定义自定义结构体 struct Person { std::string name; int age; Person(const std::string& n, int a) : name(n), age(a) {} }; // 定义仿函数,用于比较 Person 结构体 struct Compare { bool operator()(const Person& p1, const Person& p2) { return p1.age < p2.age; // 按照年龄从大到小排序 } }; int main() { // 定义优先队列,使用自定义结构体和仿函数 std::priority_queue<Person, std::vector<Person>, Compare> pq; // 向优先队列中添加元素 pq.push(Person("Alice", 25)); pq.push(Person("Bob", 30)); pq.push(Person("Charlie", 20)); // 输出优先队列中的元素 while (!pq.empty()) { const Person& p = pq.top(); std::cout << p.name << " : " << p.age << std::endl; pq.pop(); } return 0; } ``` 在上述代码中,首先定义了一个自定义结构体`Person`,包含`name`和`age`两个成员变量。然后,定义了一个仿函数`Compare`,重载了`()`运算符,用于比较两个`Person`对象的`age`成员变量。在`main`函数中,创建了一个`priority_queue`对象`pq`,并指定了自定义结构体`Person`、底层容器`std::vector<Person>`和仿函数`Compare`。最后,向优先队列中添加元素,并按照年龄从大到小的顺序输出元素。 ### 重载结构体的`>`运算符 如果不想使用仿函数,可以直接在自定义结构体中重载`>`运算符。这样,`priority_queue`就可以使用默认的比较方式来确定元素的优先级顺序。 以下是一个示例代码: ```cpp #include <iostream> #include <queue> // 定义自定义结构体 struct Point { int x; int y; Point(int _x, int _y) : x(_x), y(_y) {} // 重载 > 运算符,用于比较 Point 结构体 bool operator>(const Point& other) const { return x * x + y * y > other.x * other.x + other.y * other.y; // 按照距离原点的距离从小到大排序 } }; int main() { // 定义优先队列,使用自定义结构体 std::priority_queue<Point, std::vector<Point>, std::greater<Point>> pq; // 向优先队列中添加元素 pq.push(Point(3, 4)); pq.push(Point(1, 2)); pq.push(Point(5, 6)); // 输出优先队列中的元素 while (!pq.empty()) { const Point& p = pq.top(); std::cout << "(" << p.x << ", " << p.y << ")" << std::endl; pq.pop(); } return 0; } ``` 在上述代码中,首先定义了一个自定义结构体`Point`,包含`x`和`y`两个成员变量。然后,在结构体中重载了`>`运算符,用于比较两个`Point`对象到原点的距离。在`main`函数中,创建了一个`priority_queue`对象`pq`,并指定了自定义结构体`Point`、底层容器`std::vector<Point>`和比较函数`std::greater<Point>`。最后,向优先队列中添加元素,并按照距离原点的距离从小到大的顺序输出元素。 ### 总结 通过使用仿函数或重载`>`运算符,可以在C++的`priority_queue`中使用自定义结构体,并定义自定义的比较规则。这样,就可以根据自己的需求对自定义结构体进行排序和优先级管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值