c++优先队列使用总结,简单易懂

优先队列(Priority Queue)是一种抽象数据类型,类似于常规的队列或栈,但每个元素都有一个优先级。元素的出队顺序不是按照它们进入队列的顺序,而是根据它们的优先级。优先级最高的元素最先出队。

主要特点:

  1. 元素优先级:每个元素都有一个优先级,通常用数值表示,数值越小(或越大)优先级越高。

  2. 出队顺序:优先级最高的元素最先出队。

  3. 实现方式:优先队列通常通过堆(Heap)数据结构实现,但也可以用其他方式(如有序数组或链表)实现。

常见操作:

  1. 插入(Insert/Enqueue):将元素插入队列,并根据其优先级调整队列。

  2. 删除(Delete/Dequeue):移除并返回优先级最高的元素。

  3. 查看最高优先级元素(Peek):返回优先级最高的元素,但不移除它。

  4. 判断是否为空(Is Empty):检查队列是否为空。

实现方式:

  1. 堆(Heap)

    • 二叉堆是最常见的实现方式,分为最大堆和最小堆。

    • 插入和删除操作的时间复杂度为 O(log⁡n)O(logn)。

    • 查看最高优先级元素的时间复杂度为 O(1)O(1)。

  2. 有序数组或链表

    • 插入操作的时间复杂度为 O(n)O(n),因为需要维护顺序。

    • 删除操作的时间复杂度为 O(1)O(1)。

  3. 平衡二叉搜索树

    • 插入和删除操作的时间复杂度为 O(log⁡n)O(logn)。

    • 查看最高优先级元素的时间复杂度为 O(1)O(1)。

干货总结:

priority_queue;

type:就是元素的类型

container: 存储元素的容器(必须是数组实现的容器,如vector、deque)

functiolal: 比较规则(可用现有封装,或根据自定义的类对象进行书写比较原则)

//小顶堆
priority_queue ,greater > q;
//大顶堆
priority_queue ,less >q;
//默认大顶堆
priority_queue a;

//pair
priority_queue > a;
pair b(1, 2);
pair c(1, 3);
pair d(2, 5);
a.push(d);
a.push(c);
a.push(b);
while (!a.empty()) 
{
   cout << a.top().first << ' ' << a.top().second << '\n';
   a.pop();
}
//输出结果为:
2 5
1 3
1 2

自定义比较方式
当数据类型并不是基本数据类型,而是自定义的数据类型时,就不能用greater或less的比较方式了,而是需要自定义比较方式

举例:

struct task{
    string nume;
    int id;
    int price;
}

有两种自定义比较方式的方法,如下

1.重载运算符

重载”<”

// 根据任务代价升序排列
// 代价低为优先级高
struct task {
    string name;
    int id;
    int price;

    // 重载小于运算符(用于小顶堆)
    friend bool operator<(const task& t1, const task& t2) {
        return t1.price > t2.price;  // 代价低的优先级高
    }
};


// 根据任务代价降序排列
// 代价高为优先级高
struct task {
    string name;
    int id;
    int price;

    // 重载小于运算符(用于大顶堆)
    friend bool operator<(const task& t1, const task& t2) {
        return t1.price < t2.price;  // 代价高的优先级高
    }
};



这里为什么大小顶堆都重载了 <

1. std::priority_queue 的默认行为

std::priority_queue 是一个容器适配器,默认情况下,它使用 std::less 作为比较函数。std::less 的实现是基于 < 运算符的。

  • 默认行为

    • std::priority_queue 是一个最大堆(大顶堆)。

    • 它会将较大的元素放在堆顶。

    • 这是通过 std::less 实现的,而 std::less 内部使用的是 < 运算符。

  • 底层逻辑

    • 如果 a < b 为 true,则 b 的优先级高于 a

    • 因此,默认情况下,std::priority_queue 会按降序排列元素。


2. 为什么小顶堆也重载 <

虽然小顶堆的逻辑与默认行为相反,但我们仍然重载 < 运算符,而不是 > 运算符。这是因为:

  • std::priority_queue 只使用 < 运算符

    • std::priority_queue 的模板参数中,比较函数默认是 std::less,它只依赖于 < 运算符。

    • 即使你想实现小顶堆,也需要通过重载 < 来改变默认行为。

  • 如何实现小顶堆

    • 如果你想实现小顶堆(升序排列),需要让 < 返回 t1.price > t2.price

    • 这样,std::priority_queue 会认为较小的元素优先级更高。

2.仿函数(个人喜欢这种方式)

// 代价高为优先级,按降序存储
struct compare{
    bool operator() (const task &t1,const task&t2){
        return t1.price < t2.price;
    }

};
//此时优先队列的定义应该如下
priority_queue,compare> pq;

记忆:小根堆是大于号 >  ,大根堆是小于号 <

你可能感兴趣的:(实用技巧,c++,开发语言,优先队列,重载,仿函数)