[C++随想录] 优先级队列

简介: [C++随想录] 优先级队列

基本使用

priority_queue, 优先级队列, 又叫做双端队列, 头文件也是 <queue>

别看它叫做队列, 其实它是一个

补充一下概念:

  1. 大根堆 — — 每一棵树的父节点比它的孩子都大
  2. 小跟堆 — — 每一棵树的父节点比它的孩子都小

👇👇👇

void test()
{
  // 默认构建的是一个大堆
  priority_queue<int> pq;
  pq.push(1);
  pq.push(5);
  pq.push(4);
  pq.push(9);
  pq.push(10);
  pq.push(6);
  while (!pq.empty())
  {
    cout << pq.top() << " ";
    pq.pop();
  }
}
int main()
{
  test();
  return 0;
}

运行结果:

10 9 6 5 4 1

注意:

不要被这里的按序输出迷惑了,

优先级队列的内部结构是堆, 堆的内部结构是不一定按照元素的顺序排列的。

  • 那如果我们要 小跟堆输出呢?
void test()
{
  // 仿函数控制, greater是构建小跟堆
  priority_queue<int,vector<int>, greater<int> > pq;
  pq.push(1);
  pq.push(6);
  pq.push(20);
  pq.push(15);
  pq.push(8);
  pq.push(2);
  pq.push(6);
  pq.push(4);
  pq.push(9);
  pq.push(10);
  while (!pq.empty())
  {
    cout << pq.top() << " ";
    pq.pop();
  }
}
int main()
{
  test();
  return 0;
}

运行结果:

1 2 4 6 6 8 9 10 15 20
  1. 要构建小跟堆, 我们要用 greater
  2. 由于仿函数是最后一个参数, 那么处于中间位置的 容器适配器 也要给个参数

如何使用


  • 使用迭代区间初始化
void test()
{
  vector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(9);
  vec.push_back(8);
  vec.push_back(7);
  priority_queue<int> pq(vec.begin(), vec.end());
  while (!pq.empty())
  {
    cout << pq.top() << " ";
    pq.pop();
  }
  cout << endl;
}
int main()
{
  test();
  return 0;
}

运行结果:

9 8 7 2 1

当然我们也可以 建小堆

void test()
{
  vector<int> vec;
  vec.push_back(1);
  vec.push_back(2);
  vec.push_back(9);
  vec.push_back(8);
  vec.push_back(7);
  priority_queue<int,vector<int>, greater<int> > pq(vec.begin(), vec.end());
  while (!pq.empty())
  {
    cout << pq.top() << " ";
    pq.pop();
  }
  cout << endl;
}
int main()
{
  test();
  return 0;
}

运行结果:

1 2 7 8 9

题目训练

  1. 数组中的第K个最大元素
  2. 这是我们熟悉的 TopK问题.

那么问题来了, 要求时间复杂度是 O(n), 我们是建小堆还是大堆呢?

其实, 建小堆 和 建大堆都是一样的


建大堆

建大堆 — — 时间复杂度是 O(n)

pop (k-1) 次 — — 向上调整算法, 时间复杂度是 O(logN)

堆顶元素就是答案

总体的时间复杂度是 O(n)

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        // 1. 建大堆 
        // 建堆 -- O(n)
        priority_queue<int> pq(nums.begin(), nums.end());
        // 2. pop(k-1)次
        // pop, 向上调整算法 -- O(logN)
        while(--k)
        {
            pq.pop();
        }
        return pq.top();
    }
};

建小堆

建一个 个数为K的小堆 — — 时间复杂度是 O(K)

将剩余元素中的 大于堆顶元素的数据 插入堆中 — — 时间复杂度是 (N-K)l ogK

1. 如果 K很大, 那么时间复杂度是 O(log K)

2. 如果 K很小, 那么时间复杂度是 O(N)

返回堆顶元素

总体的时间复杂度是 O(n)

class Solution {
public:
    int findKthLargest(vector<int>& nums, int k) 
    {
        // 1. 建小堆 
        // 建堆 -- O(n)
        priority_queue<int, vector<int>, greater<int> > pq(nums.begin(), nums.begin()+k);
        // 2. pop
        // pop, 向上调整算法 -- O((N-K) logK)
        // push, 向上调整算法 -- O((N-K) logK)
        for(int i = k; i < nums.size(); i++)
        {
            if(nums[i] > pq.top())
            {
                pq.pop();
                pq.push(nums[i]);
            }
        }
        return pq.top();
    }
};


相关文章
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
335 77
|
9月前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
245 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
8月前
|
存储 算法 C++
【c++丨STL】priority_queue(优先级队列)的使用与模拟实现
本文介绍了STL中的容器适配器`priority_queue`(优先级队列)。`priority_queue`根据严格的弱排序标准设计,确保其第一个元素始终是最大元素。它底层使用堆结构实现,支持大堆和小堆,默认为大堆。常用操作包括构造函数、`empty`、`size`、`top`、`push`、`pop`和`swap`等。我们还模拟实现了`priority_queue`,通过仿函数控制堆的类型,并调用封装容器的接口实现功能。最后,感谢大家的支持与关注。
368 1
|
9月前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
141 9
|
9月前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
194 7
|
11月前
|
缓存 安全 C++
C++无锁队列:解锁多线程编程新境界
【10月更文挑战第27天】
658 7
|
11月前
|
消息中间件 存储 安全
|
12月前
|
存储 算法 调度
【C++打怪之路Lv11】-- stack、queue和优先级队列
【C++打怪之路Lv11】-- stack、queue和优先级队列
146 1
|
11月前
|
存储 设计模式 C++
【C++】优先级队列(容器适配器)
本文介绍了C++ STL中的线性容器及其适配器,包括栈、队列和优先队列的设计与实现。详细解析了`deque`的特点和存储结构,以及如何利用`deque`实现栈、队列和优先队列。通过自定义命名空间和类模板,展示了如何模拟实现这些容器适配器,重点讲解了优先队列的内部机制,如堆的构建与维护方法。
152 0
|
存储 算法 Java
【C++】优先级队列priority_queue模拟实现&&仿函数
【C++】优先级队列priority_queue模拟实现&&仿函数
98 1