📜  排序存储在不同机器上的数字

📅  最后修改于: 2021-04-17 08:46:07             🧑  作者: Mango

给定N台机器。每台机器都包含一些排序形式的数字。但是每台机器拥有的数量不是固定的。从所有机器输出的数字以无降序排列。
例子:

Machine M1 contains 3 numbers: {30, 40, 50}
       Machine M2 contains 2 numbers: {35, 45} 
       Machine M3 contains 5 numbers: {10, 60, 70, 80, 100}
       
       Output: {10, 30, 35, 40, 45, 50, 60, 70, 80, 100}

每台机器上的数字流表示形式被认为是链表。最小堆可用于按排序顺序打印所有数字。

以下是详细的过程

1.将链接列表的头指针存储在大小为N的minHeap中,其中N是机器数。

2.从minHeap中提取最小项。通过用链接列表中的下一个数字替换minHeap的头部,或者用minHeap中的最后一个数字替换minHeap的头部,然后将堆的大小减小1,来更新minHeap。

3.重复上述步骤2,直到堆不为空。

以下是上述方法的C++实现。

// A program to take numbers from different machines and print them in sorted order
#include 
  
// A Linked List node
struct ListNode
{
    int data;
    struct ListNode* next;
};
  
// A Min Heap Node
struct MinHeapNode
{
    ListNode* head;
};
  
// A Min Heao (Collection of Min Heap nodes)
struct MinHeap
{
    int count;
    int capacity;
    MinHeapNode* array;
};
  
// A function to create a Min Heap of given capacity
MinHeap* createMinHeap( int capacity )
{
    MinHeap* minHeap = new MinHeap;
    minHeap->capacity = capacity;
    minHeap->count = 0;
    minHeap->array = new MinHeapNode [minHeap->capacity];
    return minHeap;
}
  
/* A utility function to insert a new node at the beginning
   of linked list */
void push (ListNode** head_ref, int new_data)
{
    /* allocate node */
    ListNode* new_node = new ListNode;
  
    /* put in the data  */
    new_node->data  = new_data;
  
    /* link the old list off the new node */
    new_node->next = (*head_ref);
  
    /* move the head to point to the new node */
    (*head_ref)    = new_node;
}
  
// A utility function to swap two min heap nodes. This function
// is needed in minHeapify
void swap( MinHeapNode* a, MinHeapNode* b )
{
    MinHeapNode temp = *a;
    *a = *b;
    *b = temp;
}
  
// The standard minHeapify function.
void minHeapify( MinHeap* minHeap, int idx )
{
    int left, right, smallest;
    left = 2 * idx + 1;
    right = 2 * idx + 2;
    smallest = idx;
  
    if ( left < minHeap->count &&
         minHeap->array[left].head->data <
         minHeap->array[smallest].head->data
       )
        smallest = left;
  
    if ( right < minHeap->count &&
         minHeap->array[right].head->data <
         minHeap->array[smallest].head->data
       )
        smallest = right;
  
    if( smallest != idx )
    {
        swap( &minHeap->array[smallest], &minHeap->array[idx] );
        minHeapify( minHeap, smallest );
    }
}
  
// A utility function to check whether a Min Heap is empty or not
int isEmpty( MinHeap* minHeap )
{
    return (minHeap->count == 0);
}
  
// A standard function to build a heap
void buildMinHeap( MinHeap* minHeap )
{
    int i, n;
    n = minHeap->count  - 1;
    for( i = (n - 1) / 2; i >= 0; --i )
        minHeapify( minHeap, i );
}
  
// This function inserts array elements to heap and then calls
// buildHeap for heap property among nodes
void populateMinHeap( MinHeap* minHeap, ListNode* *array, int n )
{
    for( int i = 0; i < n; ++i )
        minHeap->array[ minHeap->count++ ].head = array[i];
  
    buildMinHeap( minHeap );
}
  
// Return minimum element from all linked lists
ListNode* extractMin( MinHeap* minHeap )
{
    if( isEmpty( minHeap ) )
         return NULL;
  
    // The root of heap will have minimum value
    MinHeapNode temp = minHeap->array[0];
  
    // Replace root either with next node of the same list.
    if( temp.head->next )
        minHeap->array[0].head = temp.head->next;
    else // If list empty, then reduce heap size
    {
        minHeap->array[0] = minHeap->array[ minHeap->count - 1 ];
        --minHeap->count;
    }
  
    minHeapify( minHeap, 0 );
    return temp.head;
}
  
// The main function that takes an array of lists from N machines
// and generates the sorted output
void externalSort( ListNode *array[], int N )
{
    // Create a min heap of size equal to number of machines
    MinHeap* minHeap = createMinHeap( N );
  
    // populate first item from all machines
    populateMinHeap( minHeap, array, N );
  
    while ( !isEmpty( minHeap ) )
    {
        ListNode* temp = extractMin( minHeap );
        printf( "%d ",temp->data );
    }
}
  
// Driver program to test above functions
int main()
{
    int N = 3; // Number of machines
  
    // an array of pointers storing the head nodes of the linked lists
    ListNode *array[N];
  
    // Create a Linked List 30->40->50 for first machine
    array[0] = NULL;
    push (&array[0], 50);
    push (&array[0], 40);
    push (&array[0], 30);
  
    // Create a Linked List 35->45 for second machine
    array[1] = NULL;
    push (&array[1], 45);
    push (&array[1], 35);
  
    // Create Linked List 10->60->70->80 for third machine
    array[2] = NULL;
    push (&array[2], 100);
    push (&array[2], 80);
    push (&array[2], 70);
    push (&array[2], 60);
    push (&array[2], 10);
  
    // Sort all elements
    externalSort( array, N );
  
    return 0;
}

输出:

10 30 35 40 45 50 60 70 80 100