在 C++ 中,可以使用 标准库中的 priority_queue
来实现最小堆。默认情况下,priority_queue
是一个最大堆,但可以通过自定义比较函数或使用 greater
来将其转换为最小堆。
以下是使用 priority_queue
实现最小堆,并解决多路归并问题的 C++ 代码:
C++ 实现多路归并(最小堆)
#include <iostream>
#include <vector>
#include <queue> // 包含 priority_queue
using namespace std;
// 定义链表节点
struct ListNode {
int val;
ListNode* next;
ListNode(int x) : val(x), next(nullptr) {}
};
// 自定义比较函数,用于实现最小堆
struct Compare {
bool operator()(const ListNode* a, const ListNode* b) {
return a->val > b->val; // 最小堆:小的优先级高
}
};
// 合并 K 个有序链表
ListNode* mergeKLists(vector<ListNode*>& lists) {
// 定义最小堆
priority_queue<ListNode*, vector<ListNode*>, Compare> minHeap;
// 将每个链表的头节点加入最小堆
for (ListNode* node : lists) {
if (node) {
minHeap.push(node);
}
}
// 虚拟头节点,用于简化链表操作
ListNode dummy(0);
ListNode* curr = &dummy;
// 多路归并
while (!minHeap.empty()) {
// 取出堆顶元素(当前最小节点)
ListNode* minNode = minHeap.top();
minHeap.pop();
// 将最小节点加入结果链表
curr->next = minNode;
curr = curr->next;
// 将最小节点的下一个节点加入堆
if (minNode->next) {
minHeap.push(minNode->next);
}
}
return dummy.next;
}
// 打印链表
void printList(ListNode* head) {
while (head) {
cout << head->val << " ";
head = head->next;
}
cout << endl;
}
int main() {
// 创建示例链表
ListNode* list1 = new ListNode(1);
list1->next = new ListNode(4);
list1->next->next = new ListNode(5);
ListNode* list2 = new ListNode(1);
list2->next = new ListNode(3);
list2->next->next = new ListNode(4);
ListNode* list3 = new ListNode(2);
list3->next = new ListNode(6);
// 将链表放入 vector
vector<ListNode*> lists = {list1, list2, list3};
// 合并链表
ListNode* result = mergeKLists(lists);
// 打印结果
printList(result); // 输出 1 1 2 3 4 4 5 6
return 0;
}
代码解析
-
最小堆的实现:
- 使用
priority_queue
,并自定义比较函数Compare
。 - 比较函数中,
a->val > b->val
表示小的值优先级高,从而实现最小堆。
- 使用
-
多路归并的逻辑:
- 将所有链表的头节点加入最小堆。
- 每次从堆中取出最小节点,将其加入结果链表,并将其下一个节点加入堆。
- 重复上述步骤,直到堆为空。
-
链表操作:
- 使用虚拟头节点
dummy
简化链表操作。 - 最终返回
dummy.next
作为合并后的链表头节点。
- 使用虚拟头节点
输出结果
1 1 2 3 4 4 5 6
总结
- 在 C++ 中,可以通过自定义比较函数或使用
greater
将priority_queue
转换为最小堆。 - 最小堆是多路归并问题的核心数据结构,用于高效选择当前最小元素。
- 上述代码实现了合并 K 个有序链表的功能,时间复杂度为 (O(nk \log k)),其中 (n) 是链表长度,(k) 是链表数量。