Open In App

Sort numbers stored on different machines

Improve
Improve
Improve
Like Article
Like
Save Article
Save
Share
Report issue
Report

Given N machines. Each machine contains some numbers in sorted form. But the amount of numbers, each machine has is not fixed. Output the numbers from all the machine in sorted non-decreasing form. 
Example:

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}

Representation of stream of numbers on each machine is considered as a linked list. A Min Heap can be used to print all numbers in sorted order. Following is the detailed process

  1. Store the head pointers of the linked lists in a minHeap of size N where N is a number of machines. 
  2. Extract the minimum item from the minHeap. Update the minHeap by replacing the head of the minHeap with the next number from the linked list or by replacing the head of the minHeap with the last number in the minHeap followed by decreasing the size of heap by 1. 
  3. Repeat the above step 2 until heap is not empty. Below is C++ implementation of the above approach. 

Implementation:

CPP




// A program to take numbers from different machines and print them in sorted order
#include <stdio.h>
 
// 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;
}


Java




import java.util.PriorityQueue;
 
class ListNode {
    int data;
    ListNode next;
 
    public ListNode(int data) {
        this.data = data;
        this.next = null;
    }
}
 
class MinHeapNode implements Comparable<MinHeapNode> {
    ListNode head;
 
    public MinHeapNode(ListNode head) {
        this.head = head;
    }
 
    @Override
    public int compareTo(MinHeapNode other) {
        return this.head.data - other.head.data;
    }
}
 
public class ExternalSort {
 
    // Merge K sorted linked lists using a min-heap
    public static ListNode externalSort(ListNode[] array) {
        PriorityQueue<MinHeapNode> minHeap = new PriorityQueue<>();
 
        // Add the heads of all linked lists to the min-heap
        for (ListNode node : array) {
            if (node != null) {
                minHeap.offer(new MinHeapNode(node));
            }
        }
 
        ListNode dummy = new ListNode(0);
        ListNode tail = dummy;
 
        while (!minHeap.isEmpty()) {
            MinHeapNode minNode = minHeap.poll();
            tail.next = minNode.head;
            tail = tail.next;
 
            if (minNode.head.next != null) {
                minHeap.offer(new MinHeapNode(minNode.head.next));
            }
        }
 
        return dummy.next;
    }
 
    public static void printList(ListNode head) {
        while (head != null) {
            System.out.print(head.data + " ");
            head = head.next;
        }
        System.out.println();
    }
 
    public static void main(String[] args) {
        int N = 3; // Number of machines
 
        // An array of pointers storing the head nodes of the linked lists
        ListNode[] array = new ListNode[N];
 
        // Create a Linked List 30->40->50 for the first machine
        array[0] = new ListNode(30);
        array[0].next = new ListNode(40);
        array[0].next.next = new ListNode(50);
 
        // Create a Linked List 35->45 for the second machine
        array[1] = new ListNode(35);
        array[1].next = new ListNode(45);
 
        // Create a Linked List 10->60->70->80 for the third machine
        array[2] = new ListNode(10);
        array[2].next = new ListNode(60);
        array[2].next.next = new ListNode(70);
        array[2].next.next.next = new ListNode(80);
 
        // Sort all elements
        ListNode sortedList = externalSort(array);
 
        // Print the sorted list
        System.out.println("Sorted List:");
        printList(sortedList);
    }
}


Python3




# A program to take numbers from different machines and print them in sorted order
 
# A Linked List node
class ListNode:
    def __init__(self, val=0, next=None):
        self.val = val
        self.next = next
 
# A Min Heao (Collection of Min Heap nodes)
class MinHeap:
    def __init__(self, capacity):
        self.count = 0
        self.capacity = capacity
        self.array = []
 
# A utility function to insert a new node at the beginning of linked list
def push(head_ref, new_data):
    new_node = ListNode(new_data)
    new_node.next = head_ref
    head_ref = new_node
    return head_ref
 
# A utility function to swap two min heap nodes. This function
# is needed in minHeapify
def swap(a, b):
    temp = a
    a = b
    b = temp
    return a, b
 
# The standard minHeapify function.
def min_heapify(min_heap, idx):
    left = 2 * idx + 1
    right = 2 * idx + 2
    smallest = idx
 
    if (left < min_heap.count and
            min_heap.array[left][0].val < min_heap.array[smallest][0].val):
        smallest = left
    if (right < min_heap.count and
            min_heap.array[right][0].val < min_heap.array[smallest][0].val):
        smallest = right
    if smallest != idx:
        min_heap.array[smallest], min_heap.array[idx] = swap(
            min_heap.array[smallest], min_heap.array[idx])
        min_heapify(min_heap, smallest)
 
# A utility function to check whether a Min Heap is empty or not
 
 
def is_empty(min_heap):
    return min_heap.count == 0
 
# A standard function to build a heap
def build_min_heap(min_heap):
    n = min_heap.count - 1
    for i in range((n - 1) // 2, -1, -1):
        min_heapify(min_heap, i)
 
# This function inserts array elements to heap and then calls
# buildHeap for heap property among nodes
def populate_min_heap(min_heap, array, n):
    for i in range(n):
        min_heap.array.append((array[i], i))
        min_heap.count += 1
    build_min_heap(min_heap)
 
# Return minimum element from all linked lists
def extract_min(min_heap):
    if is_empty(min_heap):
        return None
    temp = min_heap.array[0][0]
 
    if temp.next is not None:
        min_heap.array[0] = (temp.next, min_heap.array[0][1])
    else:
        min_heap.array[0] = min_heap.array[min_heap.count - 1]
        min_heap.count -= 1
 
    min_heapify(min_heap, 0)
    return temp
 
# The main function that takes an array of lists from N machines
# and generates the sorted output
def external_sort(array, n):
     # Create a min heap of size equal to number of machines
    min_heap = MinHeap(n)
 
    populate_min_heap(min_heap, array, n)
 
    while not is_empty(min_heap):
        temp = extract_min(min_heap)
        print(temp.val, end=" ")
 
 
# Driver program to test above functions
if __name__ == '__main__':
    N = 3  # Number of machines
    array = [None] * N
 
    # an array of pointers storing the head nodes of the linked lists
    array[0] = None
    array[0] = push(array[0], 50)
    array[0] = push(array[0], 40)
    array[0] = push(array[0], 30)
 
    # Create a Linked List 35->45 for second machine
    array[1] = None
    array[1] = push(array[1], 45)
    array[1] = push(array[1], 35)
 
    # Create Linked List 10->60->70->80 for third machine
 
    array[2] = None
    array[2] = push(array[2], 100)
    array[2] = push(array[2], 80)
    array[2] = push(array[2], 70)
    array[2] = push(array[2], 60)
    array[2] = push(array[2], 10)
 
    external_sort(array, N)


C#




using System;
 
// define a singly linked list node
public class ListNode {
   
      // data stored in the node
    public int data;   
   
      // reference to the next node in the linked list
    public ListNode next;    
}
 
// define a node for the heap,
// that holds a reference to a linked list node
public class MinHeapNode {
   
      // reference to a linked list node
    public ListNode head;    
}
 
// define the heap data structure
public class MinHeap {
   
      // number of nodes in the heap
    public int count;   
   
      // maximum number of nodes the heap can hold
    public int capacity; 
       
      // an array of MinHeapNode objects,
      // each containing a linked list node
    public MinHeapNode[] array;
}
 
 
public class ExternalSort {
    static MinHeap createMinHeap(int capacity) {
        MinHeap minHeap = new MinHeap();
        minHeap.capacity = capacity;
        minHeap.count = 0;
        minHeap.array = new MinHeapNode[minHeap.capacity];
        return minHeap;
    }
 
      // define a static method to add a new ListNode object
      // with specified data value to the beginning of a linked list
    static void push(ref ListNode head_ref, int new_data) {
       
        // create a new ListNode object
        ListNode new_node = new ListNode();
       
        // set the data value and next reference for the new ListNode object
        new_node.data = new_data;
        new_node.next = head_ref;
       
        // set the head reference for the linked list to the new ListNode object
        head_ref = new_node;
    }
 
    static void swap(ref MinHeapNode a, ref MinHeapNode b) {
        MinHeapNode temp = a;
        a = b;
        b = temp;
    }
   
   
    // define a static method to maintain the min heap property
      // at a given index in a MinHeap object's array
    static 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(ref minHeap.array[smallest], ref minHeap.array[idx]);
            minHeapify(minHeap, smallest);
        }
    }
 
      // A utility function to check whether a Min Heap is empty or not
    static int isEmpty(MinHeap minHeap) {
        return (minHeap.count == 0) ? 1 : 0;
    }
 
      // A standard function to build a heap
    static 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
    static void populateMinHeap(MinHeap minHeap, ListNode[] array, int n) {
        for (int i = 0; i < n; ++i) {
            MinHeapNode node = new MinHeapNode();
            node.head = array[i];
            minHeap.array[minHeap.count++] = node;
        }
        buildMinHeap(minHeap);
    }
 
 
      // Return minimum element from all linked lists
    static ListNode extractMin(MinHeap minHeap) {
        if (isEmpty(minHeap) == 1) {
            return null;
        }
 
        MinHeapNode temp = minHeap.array[0];
        ListNode node = temp.head;
 
        if (temp.head.next == null) {
            minHeap.array[0] = minHeap.array[minHeap.count - 1];
            --minHeap.count;
        }
        else {
            minHeap.array[0].head = temp.head.next;
        }
 
        minHeapify(minHeap, 0);
        return node;
    }
 
 
      // The main function that takes an array of lists from N machines
    // and generates the sorted output
    static void externalSort(ListNode[] array, int N) {
        MinHeap minHeap = createMinHeap(N);
        populateMinHeap(minHeap, array, N);
 
        while (isEmpty(minHeap) != 1) {
            ListNode temp = extractMin(minHeap);
            Console.Write(temp.data + " ");
        }
    }
 
      // Driver function
    static void Main()
    {
        int N = 3; // Number of machines
 
        // an array of pointers storing the head nodes of the linked lists
        ListNode[] array = new ListNode[N];
 
        // Create a Linked List 30->40->50 for first machine
        array[0] = null;
        push(ref array[0], 50);
        push(ref array[0], 40);
        push(ref array[0], 30);
 
        // Create a Linked List 35->45 for second machine
        array[1] = null;
        push(ref array[1], 45);
        push(ref array[1], 35);
 
        // Create Linked List 10->60->70->80 for third machine
        array[2] = null;
        push(ref array[2], 100);
        push(ref array[2], 80);
        push(ref array[2], 70);
        push(ref array[2], 60);
        push(ref array[2], 10);
 
        // Sort all elements
        externalSort(array, N);
    }
}
 
// This code is contributed by amit_mangal_


Javascript




// A JavaScript program to take numbers from different machines and print them in sorted order
 
// A Linked List node
class ListNode {
constructor(val = 0, next = null) {
this.val = val;
this.next = next;
}
}
 
// A Min Heap (Collection of Min Heap nodes)
class MinHeap {
constructor(capacity) {
this.count = 0;
this.capacity = capacity;
this.array = [];
}
}
 
// A utility function to insert a new node at the beginning of linked list
function push(head_ref, new_data) {
  /* allocate node */
const new_node = new ListNode(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;
return head_ref;
}
 
// A utility function to swap two min heap nodes. This function
// is needed in minHeapify
function swap(a, b) {
const temp = a;
a = b;
b = temp;
return [a, b];
}
 
// The standard minHeapify function.
function min_heapify(min_heap, idx) {
const left = 2 * idx + 1;
const right = 2 * idx + 2;
let smallest = idx;
 
if (
left < min_heap.count &&
min_heap.array[left][0].val < min_heap.array[smallest][0].val
) {
smallest = left;
}
if (
right < min_heap.count &&
min_heap.array[right][0].val < min_heap.array[smallest][0].val
) {
smallest = right;
}
if (smallest !== idx) {
[min_heap.array[smallest], min_heap.array[idx]] = swap(
min_heap.array[smallest],
min_heap.array[idx]
);
min_heapify(min_heap, smallest);
}
}
 
// A utility function to check whether a Min Heap is empty or not
function is_empty(min_heap) {
return min_heap.count === 0;
}
 
// A standard function to build a heap
function build_min_heap(min_heap) {
const n = min_heap.count - 1;
for (let i = Math.floor((n - 1) / 2); i >= 0; i--) {
min_heapify(min_heap, i);
}
}
 
// This function inserts array elements to heap and then calls
// buildHeap for heap property among nodes
function populate_min_heap(min_heap, array, n) {
for (let i = 0; i < n; i++) {
min_heap.array.push([array[i], i]);
min_heap.count += 1;
}
build_min_heap(min_heap);
}
 
// Return minimum element from all linked lists
function extract_min(min_heap) {
if (is_empty(min_heap)) {
return null;
}
const temp = min_heap.array[0][0];
 
if (temp.next !== null) {
min_heap.array[0] = [temp.next, min_heap.array[0][1]];
} else {
min_heap.array[0] = min_heap.array[min_heap.count - 1];
min_heap.count -= 1;
}
 
min_heapify(min_heap, 0);
return temp;
}
 
// The main function that takes an array of lists from N machines
// and generates the sorted output
function external_sort(array, n) {
  // Create a min heap of size equal to number of machines
  const min_heap = new MinHeap(n);
 
  populate_min_heap(min_heap, array, n);
 
  let sortedList = '';
  while (!is_empty(min_heap)) {
    const temp = extract_min(min_heap);
    sortedList += `${temp.val} `;
  }
  console.log(sortedList.trim());
}
 
 
// Driver program to test above functions
const N = 3; // Number of machines
const array = new Array(N);
 
// an array of pointers storing the head nodes of the linked lists
array[0] = null;
array[0] = push(array[0], 50);
array[0] = push(array[0], 40);
array[0] = push(array[0], 30);
 
// Create a Linked List 35->45 for second machine
array[1] = null;
array[1] = push(array[1], 45);
array[1] = push(array[1], 35);
 
// Create Linked List 10->60->70->80 for third machine
array[2] = null;
array[2] = push(array[2], 100);
array[2] = push(array[2], 80);
array[2] = push(array[2], 70);
array[2] = push(array[2], 60);
array[2] = push(array[2], 10);
 
external_sort(array, N);


Output

10 30 35 40 45 50 60 70 80 100 







Time complexity: O(N) for min heap
Auxiliary Space: O(N)

Approach : Using DP

This code uses a priority queue (min heap) to efficiently merge the sorted lists from different machines. The mergeLists function takes a vector of linked lists and merges them into a single sorted linked list using a min heap. The externalSort function converts the array of linked lists into a vector and then calls mergeLists to obtain the sorted list, which is then printed.

Note that this implementation assumes ascending order sorting. If you want to sort in descending order, you can modify the CompareNode struct and change the comparison operator in the operator() function accordingly.

C++




#include <iostream>
#include <vector>
#include <queue>
 
using namespace std;
 
struct ListNode {
    int data;
    ListNode* next;
};
 
struct CompareNode {
    bool operator()(const ListNode* a, const ListNode* b) {
        return a->data > b->data;
    }
};
 
ListNode* createNode(int data) {
    ListNode* newNode = new ListNode;
    newNode->data = data;
    newNode->next = nullptr;
    return newNode;
}
 
void push(ListNode** head, int data) {
    if (*head == nullptr) {
        *head = createNode(data);
    } else {
        ListNode* newNode = createNode(data);
        newNode->next = *head;
        *head = newNode;
    }
}
 
void printList(ListNode* head) {
    while (head != nullptr) {
        cout << head->data << " ";
        head = head->next;
    }
}
 
ListNode* mergeLists(vector<ListNode*>& lists) {
    ListNode* dummy = createNode(0);
    ListNode* tail = dummy;
 
    priority_queue<ListNode*, vector<ListNode*>, CompareNode> minHeap;
 
    for (ListNode* list : lists) {
        if (list != nullptr) {
            minHeap.push(list);
        }
    }
 
    while (!minHeap.empty()) {
        ListNode* node = minHeap.top();
        minHeap.pop();
 
        tail->next = node;
        tail = tail->next;
 
        if (node->next != nullptr) {
            minHeap.push(node->next);
        }
    }
 
    return dummy->next;
}
 
void externalSort(ListNode* array[], int N) {
    vector<ListNode*> lists(array, array + N);
    ListNode* sortedList = mergeLists(lists);
    printList(sortedList);
}
 
int main() {
    int N = 3; // Number of machines
 
    ListNode* array[N];
 
    array[0] = nullptr;
    push(&array[0], 50);
    push(&array[0], 40);
    push(&array[0], 30);
 
    array[1] = nullptr;
    push(&array[1], 45);
    push(&array[1], 35);
 
    array[2] = nullptr;
    push(&array[2], 100);
    push(&array[2], 80);
    push(&array[2], 70);
    push(&array[2], 60);
    push(&array[2], 10);
 
    externalSort(array, N);
 
    return 0;
}


Java




import java.util.*;
 
class ListNode {
    int data;
    ListNode next;
 
    ListNode(int data) {
        this.data = data;
        this.next = null;
    }
}
 
class CompareNode implements Comparator<ListNode> {
    @Override
    public int compare(ListNode a, ListNode b) {
        return Integer.compare(a.data, b.data);
    }
}
 
public class ExternalSorting {
 
    static ListNode createNode(int data) {
        return new ListNode(data);
    }
 
    static void push(ListNode[] head, int data, int index) {
        if (head[index] == null) {
            head[index] = createNode(data);
        } else {
            ListNode newNode = createNode(data);
            newNode.next = head[index];
            head[index] = newNode;
        }
    }
 
    static void printList(ListNode head) {
        while (head != null) {
            System.out.print(head.data + " ");
            head = head.next;
        }
    }
 
    static ListNode mergeLists(List<ListNode> lists) {
        ListNode dummy = createNode(0);
        ListNode tail = dummy;
 
        PriorityQueue<ListNode> minHeap = new PriorityQueue<>(new CompareNode());
 
        for (ListNode list : lists) {
            if (list != null) {
                minHeap.offer(list);
            }
        }
 
        while (!minHeap.isEmpty()) {
            ListNode node = minHeap.poll();
 
            tail.next = node;
            tail = tail.next;
 
            if (node.next != null) {
                minHeap.offer(node.next);
            }
        }
 
        return dummy.next;
    }
 
    static void externalSort(ListNode[] array, int N) {
        List<ListNode> lists = new ArrayList<>();
        for (ListNode node : array) {
            lists.add(node);
        }
        ListNode sortedList = mergeLists(lists);
        printList(sortedList);
    }
 
    public static void main(String[] args) {
        int N = 3; // Number of machines
 
        ListNode[] array = new ListNode[N];
 
        array[0] = null;
        push(array, 50, 0);
        push(array, 40, 0);
        push(array, 30, 0);
 
        array[1] = null;
        push(array, 45, 1);
        push(array, 35, 1);
 
        array[2] = null;
        push(array, 100, 2);
        push(array, 80, 2);
        push(array, 70, 2);
        push(array, 60, 2);
        push(array, 10, 2);
 
        externalSort(array, N);
    }
}


Python3




import heapq
 
class ListNode:
    def __init__(self, data):
        self.data = data
        self.next = None
 
def push(head, data):
    # Function to insert a new node at the beginning of a linked list
    new_node = ListNode(data)
    new_node.next = head
    head = new_node
    return head
 
def print_list(head):
    # Function to print the linked list
    while head:
        print(head.data, end=" ")
        head = head.next
    print()
 
def merge_lists(lists):
    # Function to merge K sorted linked lists into a single sorted linked list
    dummy = ListNode(0)
    tail = dummy
 
    # Use a min heap to keep track of the smallest nodes from each list
    min_heap = []
 
    for lst in lists:
        if lst:
            # Push the first node of each list into the min heap
            heapq.heappush(min_heap, (lst.data, lst))
 
    while min_heap:
        # Pop the smallest node from the min heap
        data, node = heapq.heappop(min_heap)
 
        # Append the smallest node to the sorted linked list
        tail.next = node
        tail = tail.next
 
        # If the popped node has a next node, push it into the min heap
        if node.next:
            heapq.heappush(min_heap, (node.next.data, node.next))
 
    return dummy.next
 
def external_sort(array):
    # Function to perform external sorting on an array of linked lists
    sorted_list = merge_lists(array)
    print_list(sorted_list)
 
if __name__ == "__main__":
    N = 3  # Number of machines
 
    array = [None] * N
 
    # Create the linked lists for each machine
    array[0] = None
    array[0] = push(array[0], 50)
    array[0] = push(array[0], 40)
    array[0] = push(array[0], 30)
 
    array[1] = None
    array[1] = push(array[1], 45)
    array[1] = push(array[1], 35)
 
    array[2] = None
    array[2] = push(array[2], 100)
    array[2] = push(array[2], 80)
    array[2] = push(array[2], 70)
    array[2] = push(array[2], 60)
    array[2] = push(array[2], 10)
 
    # Sort all elements
    external_sort(array)


C#




using System;
using System.Collections.Generic;
 
public class ListNode
{
    public int data;
    public ListNode next;
}
 
public class CompareNode : IComparer<ListNode>
{
    public int Compare(ListNode a, ListNode b)
    {
        return a.data.CompareTo(b.data);
    }
}
 
public class ExternalSortExample
{
    public static ListNode CreateNode(int data)
    {
        ListNode newNode = new ListNode();
        newNode.data = data;
        newNode.next = null;
        return newNode;
    }
 
    public static void Push(ref ListNode head, int data)
    {
        if (head == null)
        {
            head = CreateNode(data);
        }
        else
        {
            ListNode newNode = CreateNode(data);
            newNode.next = head;
            head = newNode;
        }
    }
 
    public static void PrintList(ListNode head)
    {
        while (head != null)
        {
            Console.Write(head.data + " ");
            head = head.next;
        }
    }
 
    public static ListNode MergeLists(List<ListNode> lists)
    {
        ListNode dummy = CreateNode(0);
        ListNode tail = dummy;
 
        // Create a priority queue using a custom comparer
        PriorityQueue<ListNode> minHeap = new PriorityQueue<ListNode>(new CompareNode());
 
        // Enqueue the initial nodes of all linked lists into the minHeap
        foreach (ListNode list in lists)
        {
            if (list != null)
            {
                minHeap.Enqueue(list);
            }
        }
 
        // Merge the lists using a min-heap
        while (minHeap.Count > 0)
        {
            ListNode node = minHeap.Dequeue();
 
            // Append the current node to the merged list
            tail.next = node;
            tail = tail.next;
 
            // If the current node has a next node, enqueue the next node
            if (node.next != null)
            {
                minHeap.Enqueue(node.next);
            }
        }
 
        return dummy.next;
    }
 
    public static void ExternalSort(ListNode[] array, int N)
    {
        List<ListNode> lists = new List<ListNode>(array);
        ListNode sortedList = MergeLists(lists);
        PrintList(sortedList);
    }
 
    public static void Main(string[] args)
    {
        int N = 3; // Number of machines
 
        // Create an array of ListNode arrays (machines)
        ListNode[] array = new ListNode[N];
 
        // Populate the arrays with data (linked lists)
        array[0] = null;
        Push(ref array[0], 50);
        Push(ref array[0], 40);
        Push(ref array[0], 30);
 
        array[1] = null;
        Push(ref array[1], 45);
        Push(ref array[1], 35);
 
        array[2] = null;
        Push(ref array[2], 100);
        Push(ref array[2], 80);
        Push(ref array[2], 70);
        Push(ref array[2], 60);
        Push(ref array[2], 10);
 
        // Perform external sorting on the arrays (linked lists)
        ExternalSort(array, N);
    }
}
 
// Priority Queue implementation using SortedSet (C#)
public class PriorityQueue<T>
{
    private SortedSet<T> set;
    private IComparer<T> comparer;
 
    public PriorityQueue(IComparer<T> comparer = null)
    {
        this.comparer = comparer ?? Comparer<T>.Default;
        this.set = new SortedSet<T>(this.comparer);
    }
 
    public int Count
    {
        get { return set.Count; }
    }
 
    public void Enqueue(T item)
    {
        set.Add(item);
    }
 
    public T Dequeue()
    {
        if (set.Count == 0)
            throw new InvalidOperationException("Priority queue is empty.");
        var item = set.Min;
        set.Remove(item);
        return item;
    }
}


Javascript




// Define a class for a ListNode, which represents a node in a linked list.
class ListNode {
    constructor(data) {
        this.data = data;
        this.next = null;
    }
}
 
// Define a class for custom comparison of ListNode objects.
class CompareNode {
    // Compare function to compare two ListNode objects based on their data values.
    compare(a, b) {
        return a.data - b.data;
    }
}
 
// Define a priority queue class for efficient element management.
class PriorityQueue {
    constructor(comparator) {
        this.comparator = comparator || ((a, b) => a - b);
        this.data = [];
    }
 
    // Getter for the count of elements in the priority queue.
    get count() {
        return this.data.length;
    }
 
    // Enqueue an item into the priority queue and maintain its order.
    enqueue(item) {
        this.data.push(item);
        this.data.sort(this.comparator);
    }
 
    // Dequeue the item with the highest priority (at the front of the queue).
    dequeue() {
        if (this.count === 0) {
            throw new Error("Priority queue is empty.");
        }
        return this.data.shift();
    }
}
 
// Function to create a new ListNode with the given data.
function createNode(data) {
    return new ListNode(data);
}
 
// Function to push a new node with data onto the head of a linked list.
function push(head, data) {
    if (!head) {
        return createNode(data);
    } else {
        const newNode = createNode(data);
        newNode.next = head;
        return newNode;
    }
}
 
// Function to print the elements in a linked list.
function printList(head) {
    let current = head;
    while (current) {
        console.log(current.data + ' ');
        current = current.next;
    }
}
 
// Function to merge a list of linked lists into a single sorted linked list.
function mergeLists(lists) {
    const dummy = createNode(0);
    let tail = dummy;
 
    // Create a priority queue to efficiently manage the elements.
    const minHeap = new PriorityQueue((a, b) => a.data - b.data);
 
    // Enqueue the initial nodes of all linked lists into the priority queue.
    lists.forEach(list => {
        if (list !== null) {
            minHeap.enqueue(list);
        }
    });
 
    // Merge the lists using the priority queue (min-heap).
    while (minHeap.count > 0) {
        const node = minHeap.dequeue();
        tail.next = node;
        tail = tail.next;
 
        // If the current node has a next node, enqueue the next node.
        if (node.next !== null) {
            minHeap.enqueue(node.next);
        }
    }
 
    return dummy.next;
}
 
// Function to perform external sorting on an array of linked lists.
function externalSort(array, N) {
    const lists = array;
    const sortedList = mergeLists(lists);
    printList(sortedList);
}
 
// Main function where we set up the example and call the externalSort function.
function main() {
    const N = 3; // Number of machines
 
    // Create an array of linked lists representing data from different machines.
    const array = new Array(N);
 
    // Populate the arrays with data (linked lists).
    array[0] = null;
    array[0] = push(array[0], 50);
    array[0] = push(array[0], 40);
    array[0] = push(array[0], 30);
 
    array[1] = null;
    array[1] = push(array[1], 45);
    array[1] = push(array[1], 35);
 
    array[2] = null;
    array[2] = push(array[2], 100);
    array[2] = push(array[2], 80);
    array[2] = push(array[2], 70);
    array[2] = push(array[2], 60);
    array[2] = push(array[2], 10);
 
    // Perform external sorting on the arrays (linked lists).
    externalSort(array, N);
}
 
// Call the main function to execute the example.
main();


Output:

10 30 35 40 45 50 60 70 80 100 

space complexity: O(N + K)

time complexity: O(N + K log N)



Last Updated : 29 Oct, 2023
Like Article
Save Article
Previous
Next
Share your thoughts in the comments
Similar Reads