多路归并

   问题:设计一个算法将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;
}
原文地址:https://www.cnblogs.com/td15980891505/p/5166678.html