| 特性 | queue | priority_queue |
|---|---|---|
| 顺序 | FIFO(先进先出) | 按优先级 |
| 访问 | front/back | top |
| 底层 | deque/list | 堆(vector) |
双向队列:deque
priority_queue 是 C++ 标准库中的优先队列 容器适配器。它基于堆 结构实现,默认是一个最大堆(队首元素始终是最大的元素)。
1. 最大堆(默认)
priority_queue<int> pq; // 最大的元素在堆顶
priority_queue<int, vector<int>, less<int>> pq; // 等价写法
2. 最小堆
priority_queue<int, vector<int>, greater<int>> pq; // 最小的元素在堆顶
3. 自定义类型
// 方法一:重载 < 运算符
struct Node {
int val, priority;
bool operator<(const Node& other) const {
return priority < other.priority; // 注意:这里定义的是"小于"关系
}
};
priority_queue<Node> pq;
// 方法二:自定义比较函数对象
struct Compare {
bool operator()(const Node& a, const Node& b) {
return a.priority > b.priority; // 最小堆
}
};
priority_queue<Node, vector<Node>, Compare> pq;
class Solution {
public:
struct node{
int val;
ListNode* ptr;
bool operator < (const node &t) const{
return val > t.val;//实现最小堆
}
};
priority_queue<node> q;
ListNode* mergeKLists(vector<ListNode*>& lists) {
for(auto n:lists){
if(n) q.push({n->val,n});//把每个头先压进队列
}
ListNode head,*tail=&head;
while(!q.empty()){
auto f=q.top();
q.pop();
tail->next=f.ptr;
tail=tail->next;
if(f.ptr->next) q.push({f.ptr->next->val,f.ptr->next});
}
return head.next;
}
};
两两合并
class Solution {
public:
ListNode* mergeTwoLists(ListNode *a, ListNode *b) {
if ((!a) || (!b)) return a ? a : b;
ListNode head, *tail = &head, *aPtr = a, *bPtr = b;
while (aPtr && bPtr) {
if (aPtr->val < bPtr->val) {
tail->next = aPtr; aPtr = aPtr->next;
} else {
tail->next = bPtr; bPtr = bPtr->next;
}
tail = tail->next;
}
tail->next = (aPtr ? aPtr : bPtr);
return head.next;
}
ListNode* mergeKLists(vector<ListNode*>& lists) {
ListNode *ans = nullptr;
for (size_t i = 0; i < lists.size(); ++i) {
ans = mergeTwoLists(ans, lists[i]);
}
return ans;
}
};
分治法(两两归并):
mergeKLists (入口)
└── merge (分治函数)
├── 递归分割左半部分
├── 递归分割右半部分
└── mergeTwoLists (合并两个有序链表)
ListNode* merge(vector<ListNode*> &lists, int l, int r) {
if (l == r) return lists[l]; // 只有一个链表,直接返回
if (l > r) return nullptr; // 区间无效,返回空
int mid = (l + r) >> 1; // 取中点(等价于 (l+r)/2)
// 递归合并左右两部分
return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r));
}
递归过程:
-
分割 :将区间
[l, r]分成[l, mid]和[mid+1, r] -
递归:分别对左右区间执行相同的分割
-
合并:将左右两个有序链表合并
-
假设有 4 个链表:
[L1, L2, L3, L4]
merge(0,3)
/ \
merge(0,1) merge(2,3)
/ \ / \
merge(0,0) merge(1,1) merge(2,2) merge(3,3)
L1 L2 L3 L4
\ / \ /
mergeTwoLists mergeTwoLists
(L1,L2) (L3,L4)
\ /
mergeTwoLists((L1,L2), (L3,L4))
|
最终结果
-
具体合并顺序:
-
递归到底:得到
L1,L2,L3,L4 -
第一次合并:
mergeTwoLists(L1, L2)→L12 -
第一次合并:
mergeTwoLists(L3, L4)→L34 -
最终合并:
mergeTwoLists(L12, L34)→ 结果class Solution { public: ListNode* mergeTwoLists(ListNode *a, ListNode *b) { if ((!a) || (!b)) return a ? a : b; ListNode head, *tail = &head, *aPtr = a, *bPtr = b; while (aPtr && bPtr) { if (aPtr->val < bPtr->val) { tail->next = aPtr; aPtr = aPtr->next; } else { tail->next = bPtr; bPtr = bPtr->next; } tail = tail->next; } tail->next = (aPtr ? aPtr : bPtr); return head.next; } ListNode* merge(vector <ListNode*> &lists, int l, int r) { if (l == r) return lists[l]; if (l > r) return nullptr; int mid = (l + r) >> 1; return mergeTwoLists(merge(lists, l, mid), merge(lists, mid + 1, r)); } ListNode* mergeKLists(vector<ListNode*>& lists) { return merge(lists, 0, lists.size() - 1); } }