优先队列知识点(带结构体排列方式)

本文介绍了C++中的优先队列,强调了其默认排序规则是从大到小,并提供了如何自定义排序规则以实现从小到大的示例。在处理结构体时,优先队列的排序行为可能与预期相反,文章通过代码实例展示了这一特性。

记住优先队列都是反着来的

  • priority_queue q;
    默认为由大到小 (与sort默认由小到大相反)

  • priority_queue<int, std::vector, std::greater > q;
    由小到大排序

/* 
	*
	将 1-9 压入队列中
	1. std::priority_queue<int> q;  -> 从大到小排列
	2. std::priority_queue<int, std::vector<int>, std::greater<int> > q2; ->从小到大 
	3.用 lambda 比较元素。//没理解 

*/
#include <functional>
#include <queue>
#include <vector>
#include <iostream>
//using namespace std;
template<typename T> void print_queue(T& q) {
    while(!q.empty()) {
        std::cout << q.top() << " ";
        q.pop();
    }
    std::cout << '\n';
}
 
int main() {
    std::priority_queue<int> q;
 
    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q.push(n);
        
 	//输出为 9 8 7 6 5 4 3 2 1 0 
 
    print_queue(q);
 
    std::priority_queue<int, std::vector<int>, std::greater<int> > q2;
 
    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q2.push(n);
 
 	//输出为0 1 2 3 4 5 6 7 8 9 
 	
    print_queue(q2);
 
    // 用 lambda 比较元素。
    auto cmp = [](int left, int right) { return (left ^ 1) < (right ^ 1); };
    std::priority_queue<int, std::vector<int>, decltype(cmp)> q3(cmp);
 
    for(int n : {1,8,5,6,3,4,0,9,7,2})
        q3.push(n);
 	
 	//输出为8 9 6 7 4 5 2 3 0 1 
 
    print_queue(q3);
 
}

/*
output
9 8 7 6 5 4 3 2 1 0 
0 1 2 3 4 5 6 7 8 9 
8 9 6 7 4 5 2 3 0 1
*/ 
  • 加入结构体的排序,并同时规定排序方式
struct node
{
	int x,y;
}k;
struct cmp1    //另辟struct,排序自定义
{
	bool operator () (const node & a,const node & b) const
	{
	    if(b.x!=a.x) return b.x<a.x;
        else  return b.y>a.y;
	}
};

很坑的一点就是优先队列的规则设定和最终出来的刚好相反,详情见下面代码实例

priority_queue <node,vector<node>,cmp1> q;  //优先列队写法
#include<cstdio>
#include<queue>
#include<algorithm>
#include<iostream>
using namespace std;
struct node
{
	int x,y;
}k;
 
bool cmp(int a,int b)
{
	return a>b;
}


struct cmp1    //另辟struct,排序自定义
{
	bool operator () (const node & a,const node & b) const
	{
	    if(b.x!=a.x) return b.x<a.x;
        else  return b.y>a.y;
	}
};

priority_queue <node,vector<node>,cmp1> q;  //优先列队写法

int main()
{
	int e[] = {5,4,8,2,6,7,9};	//7个 
	sort(e,e+7,cmp);
	for(int i = 0;i<7;i++)
		cout<<e[i]<<" ";
	cout<<endl<<endl;
	
	k.x=10,k.y=100; q.push(k);
	k.x=12,k.y=60; q.push(k);
	k.x=12,k.y=40; q.push(k);
	k.x=6,k.y=80; q.push(k);
	k.x=8,k.y=20; q.push(k);
	while(!q.empty())
	{
		node m=q.top(); q.pop();
		printf("(%d,%d) ",m.x,m.y);
	}
}

输出为

  • (6,80) (8,20) (10,100) (12,60) (12,40)

按照原本sort定义cmp的习惯输出应该是x轴由大到小,相同x轴由小到大,这里完全反过来,留意

ε=ε=ε=┏(゜ロ゜;)┛

### C++ 优先队列在面试中的常见考察点 #### 1. 基本概念与默认行为 C++ 中的 `priority_queue` 是一种容器适配器,基于堆结构实现。默认情况下,它是一个最大堆,即队列顶部始终是当前队列中最大的元素[^1]。 ```cpp #include <queue> std::priority_queue<int> pq; // 默认为最大堆 pq.push(5); pq.push(10); pq.push(3); std::cout << pq.top(); // 输出 10 ``` #### 2. 自定义比较函数 面试中常考察如何通过自定义比较函数实现最小堆或其他排序规则。可以通过重载运算符、使用仿函数或标准库中的比较函数对象(如 `std::greater` 和 `std::less`)来实现[^2]。 ```cpp // 最小堆示例 std::priority_queue<int, std::vector<int>, std::greater<int>> minQueue; minQueue.push(5); minQueue.push(10); minQueue.push(3); std::cout << minQueue.top(); // 输出 3 ``` #### 3. 存储复杂数据类型 当优先队列需要存储复杂数据类型(如 `pair` 或自定义结构体)时,面试可能会要求设计适当的比较逻辑。以下是一个按第二个元素排序的示例[^3]: ```cpp struct Compare { bool operator()(const std::pair<int, int>& a, const std::pair<int, int>& b) const { return a.second > b.second; // 按第二个元素升序排列 } }; std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, Compare> queue; queue.push({1, 10}); queue.push({2, 5}); queue.push({3, 20}); std::cout << queue.top().first << " " << queue.top().second; // 输出 2 5 ``` #### 4. 时间复杂度与应用场景 优先队列的时间复杂度通常是面试中的重点。插入和删除操作的时间复杂度均为 \(O(\log n)\),获取顶部元素的时间复杂度为 \(O(1)\)。常见的应用场景包括: - 实现 Dijkstra 算法或 Prim 算法中的最小生成树问题。 - 处理任务调度问题,例如按优先级分配任务。 - 实现 Top-K 问题,如找出数组中前 K 个最大值。 #### 5. 线程安全性 在多线程环境中,`std::priority_queue` 并不是线程安全的。如果需要在多线程场景下使用,通常需要结合互斥锁(如 `std::mutex`)来保证安全性[^4]。 #### 6. STL 容器适配器的理解 面试可能会涉及对 STL 容器适配器的理解。`priority_queue` 是一种容器适配器,底层默认使用 `std::vector` 实现。可以通过模板参数指定其他底层容器,例如 `std::deque`[^5]。 ```cpp std::priority_queue<int, std::deque<int>> dequeBasedPQ; ``` #### 7. 虚函数表与继承 虽然优先队列本身不直接涉及虚函数表,但面试可能会延伸到相关知识点。例如,如何通过继承实现自定义比较逻辑,并确保基类的析构函数为虚函数以避免资源泄漏[^6]。 #### 8. 内存管理与智能指针 在某些高级场景下,优先队列可能存储智能指针(如 `std::shared_ptr` 或 `std::unique_ptr`)。面试可能会考察如何正确管理内存,以及智能指针的引用计数机制[^7]。 ```cpp std::priority_queue<std::shared_ptr<int>> ptrQueue; ptrQueue.push(std::make_shared<int>(5)); ptrQueue.push(std::make_shared<int>(10)); ``` #### 9. 大顶堆与小顶堆的应用场景 大顶堆(最大堆)和小顶堆(最小堆)在实际应用中有不同的用途。例如: - 大顶堆:用于实现优先级队列,处理高优先级任务。 - 小顶堆:用于实现 Top-K 问题,或者作为最小生成树算法的一部分。 #### 10. STL 的实现细节 面试可能会深入到 STL 的实现细节,例如优先队列如何基于堆实现,以及 `std::make_heap`、`std::push_heap` 和 `std::pop_heap` 的作用[^8]。 --- ### 示例代码:Top-K 问题 以下是一个使用优先队列解决 Top-K 问题的示例: ```cpp #include <iostream> #include <queue> #include <vector> int findKthLargest(std::vector<int>& nums, int k) { std::priority_queue<int, std::vector<int>, std::greater<int>> minHeap; for (const auto& num : nums) { minHeap.push(num); if (minHeap.size() > k) { minHeap.pop(); } } return minHeap.top(); } int main() { std::vector<int> nums = {3, 2, 1, 5, 6, 4}; int k = 2; std::cout << "The " << k << "th largest element is: " << findKthLargest(nums, k) << std::endl; return 0; } ``` --- ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值