问题:设计一个算法将k个有序链表合并成一个有序链表,已知k个链表总元素个数为n.
算法要求的复杂度是O(nlogk),可以采用最小堆来实现k路归并,具体算法如下:
1.取出k个链表头结点调准成一个最小堆heap[k];
2.取出堆heap中的最小值,然后将该最小值下一个结点放在heap[0]位置,然后调准heap再次成为最小堆。入过该最小值下一个结点不存在,就删除heap[0],调准最小堆heap,元素个数减一。
3.重复步骤2,知道k个链表都为空。
c++代码如下:
#include<iostream> using namespace std; struct Node { int value; Node*next; }; Node *Build_Node(int m); //创建元素个数为m的链表 void MinHeap_Pihy(Node *A[], int n, int i); void BuildMinHeap(Node *A[], int n); //建立最小堆 Node*Push(Node*A[], int n); //返回堆顶元素并且堆元素个数减一 Node*MergeK(Node*heap[], int k, int n); //K路归并 void Print_Node(Node*head) { Node*p = head; while (p) { cout << p->value << " "; p = p->next; } cout << endl; } int main() { int m1, m2, m3; Node*heap[3]{ NULL }; cin >> m1; heap[0] = Build_Node(m1); cin >> m2; heap[1] = Build_Node(m2); cin >> m3; heap[2] = Build_Node(m3); Node*head = MergeK(heap, 3, m1 + m2 + m3); Print_Node(head); return 0; } Node *Build_Node(int m) { Node*head = new Node; Node*p1 = head, *p2 = head; cin >> head->value; for (int i = 1; i < m; i++) { p1 = new Node; cin >> p1->value; p2->next = p1; p2 = p2->next; } p2->next = NULL; return head; } void MinHeap_Pihy(Node*A[], int n, int i) { //在A中调准第i个元素向下过滤 int left, child; for (left = i * 2 + 1; left <n; left = i * 2 + 1) { child = i; if (A[left]->value<A[child]->value) child = left; if (left + 1 <n&&A[left + 1]->value<A[child]->value) child = left + 1; if (i == child) break; swap(A[child], A[i]); i = child; } } void BuildMinHeap(Node* A[], int n) { for (int i = n / 2 - 1; i >= 0; i--) MinHeap_Pihy(A, n, i); } Node*Push(Node*A[], int n) { Node*p = A[0]; A[0] = A[n - 1]; MinHeap_Pihy(A, n - 1, 0); return p; } Node*MergeK(Node*heap[], int k, int n) { Node*head = new Node; //设置一个空头结点 Node*p1 = head, *p2 = head; BuildMinHeap(heap, k); for (int i = 0; i < n; i++) { if (heap[0]->next == NULL) { //堆顶元素下一个结点为空时 p1 = Push(heap, k); k--; } else { p1 = heap[0]; heap[0] = p1->next; MinHeap_Pihy(heap, k, 0); } p2->next = p1; p2 = p2->next; } p2->next = NULL; p1 = head; head = head->next; delete p1; //删除空头结点 return head; }