Programa C++ para fusionar listas enlazadas ordenadas K – Conjunto 1

Dadas K listas enlazadas ordenadas de tamaño N cada una, combínelas e imprima la salida ordenada.

Ejemplos: 

Input: k = 3, n =  4
list1 = 1->3->5->7->NULL
list2 = 2->4->6->8->NULL
list3 = 0->9->10->11->NULL

Output: 0->1->2->3->4->5->6->7->8->9->10->11
Merged lists in a sorted order 
where every element is greater 
than the previous element.

Input: k = 3, n =  3
list1 = 1->3->7->NULL
list2 = 2->4->8->NULL
list3 = 9->10->11->NULL

Output: 1->2->3->4->7->8->9->10->11
Merged lists in a sorted order 
where every element is greater 
than the previous element.

Método 1 (Simple):

Enfoque: 
una solución simple es inicializar el resultado como la primera lista. Ahora recorra todas las listas a partir de la segunda lista. Inserte cada Node de la lista recorrida actualmente en el resultado de forma ordenada.  

C++

// C++ program to merge k sorted
// linked lists of size n each
#include <bits/stdc++.h>
using namespace std;
  
// A Linked List node
struct Node 
{
    int data;
    Node* next;
};
  
/* Function to print nodes in a 
   given linked list */
void printList(Node* node)
{
    while (node != NULL) 
    {
        printf("%d ", node->data);
        node = node->next;
    }
}
  
// The main function that takes an 
// array of lists arr[0..last] and 
// generates the sorted output
Node* mergeKLists(Node* arr[], 
                  int last)
{
    // Traverse form second list to last
    for (int i = 1; i <= last; i++) 
    {
        while (true) 
        {
            // Head of both the lists,
            // 0 and ith list.
            Node *head_0 = arr[0], 
                 *head_i = arr[i];
  
            // Break if list ended
            if (head_i == NULL)
                break;
  
            // Smaller than first element
            if (head_0->data >= head_i->data) 
            {
                arr[i] = head_i->next;
                head_i->next = head_0;
                arr[0] = head_i;
            }
            else
                // Traverse the first list
                while (head_0->next != NULL) 
                {
                    // Smaller than next element
                    if (head_0->next->data >= 
                        head_i->data) 
                    {
                        arr[i] = head_i->next;
                        head_i->next = head_0->next;
                        head_0->next = head_i;
                        break;
                    }
                    // go to next node
                    head_0 = head_0->next;
  
                    // if last node
                    if (head_0->next == NULL) 
                    {
                        arr[i] = head_i->next;
                        head_i->next = NULL;
                        head_0->next = head_i;
                        head_0->next->next = NULL;
                        break;
                    }
                }
        }
    }
    return arr[0];
}
  
// Utility function to create 
// a new node.
Node* newNode(int data)
{
    struct Node* temp = new Node;
    temp->data = data;
    temp->next = NULL;
    return temp;
}
  
// Driver code
int main()
{
    // Number of linked lists
    int k = 3;
  
    // Number of elements in each list
    int n = 4;
  
    // an array of pointers storing the
    // head nodes of the linked lists
    Node* arr[k];
  
    arr[0] = newNode(1);
    arr[0]->next = newNode(3);
    arr[0]->next->next = newNode(5);
    arr[0]->next->next->next = newNode(7);
  
    arr[1] = newNode(2);
    arr[1]->next = newNode(4);
    arr[1]->next->next = newNode(6);
    arr[1]->next->next->next = newNode(8);
  
    arr[2] = newNode(0);
    arr[2]->next = newNode(9);
    arr[2]->next->next = newNode(10);
    arr[2]->next->next->next = newNode(11);
  
    // Merge all lists
    Node* head = mergeKLists(arr, k - 1);
  
    printList(head);
  
    return 0;
}

Producción:

0 1 2 3 4 5 6 7 8 9 10 11

Análisis de Complejidad: 

  • Complejidad del tiempo: O(nk 2 )
  • Espacio Auxiliar: O(1). 
    Como no se requiere espacio adicional.

Método 2: montón mínimo
Una mejor solución es usar una solución basada en Min Heap que se analiza aquí para arreglos. La complejidad temporal de esta solución sería O(nk Log k)
Método 3: divide y vencerás
En esta publicación, se analiza el enfoque Divide and Conquer . Este enfoque no requiere espacio adicional para el almacenamiento dinámico y funciona en O(nk Log k).
Se sabe que la fusión de dos listas enlazadas se puede realizar en tiempo O(n) y espacio O(n). 

  1. La idea es emparejar K listas y fusionar cada par en tiempo lineal usando el espacio O(n).
  2. Después del primer ciclo, se dejan listas K/2 cada una de tamaño 2*N. Después del segundo ciclo, se dejan listas K/4 cada una de tamaño 4*N y así sucesivamente.
  3. Repita el procedimiento hasta que solo nos quede una lista.

A continuación se muestra la implementación de la idea anterior. 

C++

// C++ program to merge k sorted
// linked lists of size n each
#include <bits/stdc++.h>
using namespace std;
  
// A Linked List node
struct Node 
{
    int data;
    Node* next;
};
  
/* Function to print nodes in a 
   given linked list */
void printList(Node* node)
{
    while (node != NULL) 
    {
        printf("%d ", node->data);
        node = node->next;
    }
}
  
/* Takes two lists sorted in increasing order, 
   and merge their nodes together to make one 
   big sorted list. Below function takes O(n) 
   extra space for recursive calls, */
Node* SortedMerge(Node* a, Node* b)
{
    Node* result = NULL;
  
    // Base cases 
    if (a == NULL)
        return (b);
    else if (b == NULL)
        return (a);
  
    // Pick either a or b, and recur 
    if (a->data <= b->data) 
    {
        result = a;
        result->next = SortedMerge(a->next, b);
    }
    else 
    {
        result = b;
        result->next = SortedMerge(a, b->next);
    }
  
    return result;
}
  
// The main function that takes an 
// array of lists arr[0..last] and 
// generates the sorted output
Node* mergeKLists(Node* arr[], int last)
{
    // Repeat until only one list is left
    while (last != 0) 
    {
        int i = 0, j = last;
  
        // (i, j) forms a pair
        while (i < j) 
        {
            // merge List i with List j and 
            // store merged list in List i
            arr[i] = SortedMerge(arr[i], arr[j]);
  
            // consider next pair
            i++, j--;
  
            // If all pairs are merged, update 
            // last
            if (i >= j)
                last = j;
        }
    }
  
    return arr[0];
}
  
// Utility function to create 
// a new node.
Node* newNode(int data)
{
    struct Node* temp = new Node;
    temp->data = data;
    temp->next = NULL;
    return temp;
}
  
// Driver code
int main()
{
    // Number of linked lists
    int k = 3; 
  
    // Number of elements in 
    // each list
    int n = 4; 
  
    // An array of pointers storing 
    // the head nodes of the linked lists
    Node* arr[k];
  
    arr[0] = newNode(1);
    arr[0]->next = newNode(3);
    arr[0]->next->next = newNode(5);
    arr[0]->next->next->next = newNode(7);
  
    arr[1] = newNode(2);
    arr[1]->next = newNode(4);
    arr[1]->next->next = newNode(6);
    arr[1]->next->next->next = newNode(8);
  
    arr[2] = newNode(0);
    arr[2]->next = newNode(9);
    arr[2]->next->next = newNode(10);
    arr[2]->next->next->next = newNode(11);
  
    // Merge all lists
    Node* head = mergeKLists(arr, k - 1);
  
    printList(head);
  
    return 0;
}

Producción:

0 1 2 3 4 5 6 7 8 9 10 11

Análisis de Complejidad: 

Suponiendo que N(n*k) es el número total de Nodes, n es el tamaño de cada lista vinculada y k es el número total de listas vinculadas.

  • Complejidad de tiempo: O(N*log k) u O(n*k*log k)
    Como ciclo while externo en la función mergeKLists() ejecuta log k veces y cada vez que procesa n*k elementos.
  • Espacio auxiliar: O(N) u O(n*k)
    Debido a que la recursividad se usa en SortedMerge() y para fusionar las 2 listas enlazadas finales de tamaño N/2, se realizarán N llamadas recursivas.

Consulte el artículo completo sobre las listas enlazadas ordenadas de Merge K | ¡ Establezca 1 para más detalles!

Publicación traducida automáticamente

Artículo escrito por GeeksforGeeks-1 y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *