Programa C++ para reorganizar una lista enlazada dada en el lugar.

Dada una lista unida L 0 -> L 1 -> … -> L n-1 -> L n . Reorganice los Nodes en la lista para que la nueva lista formada sea: L 0 -> L n -> L 1 -> L n-1 -> L 2 -> L n-2
Debe hacer esto en su lugar sin alterando los valores de los Nodes. 

Ejemplos: 

Input: 1 -> 2 -> 3 -> 4
Output: 1 -> 4 -> 2 -> 3

Input: 1 -> 2 -> 3 -> 4 -> 5
Output: 1 -> 5 -> 2 -> 4 -> 3

Solución simple:

1) Initialize current node as head.
2) While next of current node is not null, do following
    a) Find the last node, remove it from the end and insert it as next
       of the current node.
    b) Move current to next to next of current

La complejidad temporal de la solución simple anterior es O(n 2 ) donde n es el número de Nodes en la lista enlazada.

Mejor solución: 
1) Copie el contenido de la lista vinculada dada a un vector. 
2) Reorganizar el vector dado intercambiando Nodes de ambos extremos. 
3) Copie el vector modificado nuevamente a la lista enlazada. 
Implementación de este enfoque: https://ide.geeksforgeeks.org/1eGSEy 
Gracias a Arushi Dhamija por sugerir este enfoque.

Solución eficiente:

1) Find the middle point using tortoise and hare method.
2) Split the linked list into two halves using found middle point in step 1.
3) Reverse the second half.
4) Do alternate merge of first and second halves.

La complejidad temporal de esta solución es O(n). 

A continuación se muestra la implementación de este método.

C++

// C++ program to rearrange a
// linked list in-place
#include <bits/stdc++.h>
using namespace std;
 
// Linkedlist Node structure
struct Node
{
    int data;
    struct Node* next;
};
 
// Function to create newNode
// in a linkedlist
Node* newNode(int key)
{
    Node* temp = new Node;
    temp->data = key;
    temp->next = NULL;
    return temp;
}
 
// Function to reverse the
// linked list
void reverselist(Node** head)
{
    // Initialize prev and current
    // pointers
    Node *prev = NULL,
         *curr = *head, *next;
 
    while (curr)
    {
        next = curr->next;
        curr->next = prev;
        prev = curr;
        curr = next;
    }
 
    *head = prev;
}
 
// Function to print the
// linked list
void printlist(Node* head)
{
    while (head != NULL)
    {
        cout << head->data << " ";
        if (head->next)
            cout << "-> ";
        head = head->next;
    }
    cout << endl;
}
 
// Function to rearrange a
// linked list
void rearrange(Node** head)
{
    // 1) Find the middle point using
    // tortoise and hare method
    Node *slow = *head,
         *fast = slow->next;
    while (fast && fast->next)
    {
        slow = slow->next;
        fast = fast->next->next;
    }
 
    // 2) Split the linked list in
    // two halves
    // head1, head of first half- 1 -> 2
    // head2, head of second half- 3 -> 4
    Node* head1 = *head;
    Node* head2 = slow->next;
    slow->next = NULL;
 
    // 3) Reverse the second half,
    // i.e.,  4 -> 3
    reverselist(&head2);
 
    // 4) Merge alternate nodes
    // Assign dummy Node
    *head = newNode(0);
 
    // curr is the pointer to this
    // dummy Node, which will be
    // used to form the new list
    Node* curr = *head;
    while (head1 || head2)
    {
        // First add the element
        // from list
        if (head1)
        {
            curr->next = head1;
            curr = curr->next;
            head1 = head1->next;
        }
 
        // Then add the element from
        // the second list
        if (head2)
        {
            curr->next = head2;
            curr = curr->next;
            head2 = head2->next;
        }
    }
 
    // Assign the head of the new
    // list to head pointer
    *head = (*head)->next;
}
 
// Driver program
int main()
{
    Node* head = newNode(1);
    head->next = newNode(2);
    head->next->next = newNode(3);
    head->next->next->next = newNode(4);
    head->next->next->next->next = newNode(5);
 
    printlist(head); // Print original list
    rearrange(&head); // Modify the list
    printlist(head); // Print modified list
    return 0;
}

Producción:

1 -> 2 -> 3 -> 4 -> 5 
1 -> 5 -> 2 -> 4 -> 3

Complejidad de tiempo: O(n) 
Espacio auxiliar: O(1)
Gracias a Gaurav Ahirwar por sugerir el enfoque anterior.

Otro enfoque: 
1. Tome dos punteros prev y curr, que contienen las direcciones de head y head-> next. 
2. Compare sus datos e intercambie. 
Después de eso, se forma una nueva lista enlazada. 

A continuación se muestra la implementación: 

C++

// C++ code to rearrange linked list
// in place
#include <bits/stdc++.h>
using namespace std;
 
struct node
{
    int data;
    struct node* next;
};
typedef struct node Node;
 
// Function for rearranging a
// linked list with high and low
// value.
void rearrange(Node* head)
{
    // Base case.
    if (head == NULL)
        return;
 
    // Two pointer variable.
    Node *prev = head,
         *curr = head->next;
 
    while (curr)
    {
        // Swap function for swapping data.
        if (prev->data > curr->data)
            swap(prev->data, curr->data);
 
        // Swap function for swapping data.
        if (curr->next &&
            curr->next->data > curr->data)
            swap(curr->next->data, curr->data);
 
        prev = curr->next;
 
        if (!curr->next)
            break;
        curr = curr->next->next;
    }
}
 
// Function to insert a node in the
// linked list at the beginning.
void push(Node** head, int k)
{
    Node* tem = (Node*)malloc(sizeof(Node));
    tem->data = k;
    tem->next = *head;
    *head = tem;
}
 
// Function to display node of
// linked list.
void display(Node* head)
{
    Node* curr = head;
    while (curr != NULL)
    {
        printf("%d ", curr->data);
        curr = curr->next;
    }
}
 
// Driver code
int main()
{
    Node* head = NULL;
 
    // Let create a linked list.
    // 9 -> 6 -> 8 -> 3 -> 7
    push(&head, 7);
    push(&head, 3);
    push(&head, 8);
    push(&head, 6);
    push(&head, 9);
 
    rearrange(head);
    display(head);
 
    return 0;
}

Producción:

6 9 3 8 7

Complejidad de tiempo: O(n) 
Espacio auxiliar: O(1) 
Gracias a Aditya por sugerir este enfoque.

Otro enfoque: (usando la recursividad)

  1. Mantenga un puntero en el Node principal y vaya hasta el último Node usando recursividad
  2. Una vez que se alcanza el último Node, comience a intercambiar el último Node con el siguiente Node principal
  3. Mover el puntero de la cabeza al siguiente Node
  4. Repita esto hasta que la cabeza y el último Node se encuentren o queden adyacentes entre sí.
  5. Una vez que se cumplió la condición de parada, debemos descartar los Nodes de la izquierda para corregir el bucle creado en la lista al intercambiar Nodes.

C++

// C/C++ program to implement
// the above approach
#include <stdio.h>
#include <stdlib.h>
 
// Creating the structure
// for node
struct Node
{
    int data;
    struct Node* next;
};
 
// Function to create newNode
// in a linkedlist
struct Node* newNode(int key)
{
    struct Node* temp =
           malloc(sizeof(struct Node));
    temp->data = key;
    temp->next = NULL;
    return temp;
}
 
// Function to print the list
void printlist(struct Node* head)
{
    while (head)
    {
        printf("%d ", head->data);
        if (head->next)
            printf("->");
        head = head->next;
    }
    printf("");
}
 
// Function to rearrange
void rearrange(struct Node** head,
               struct Node* last)
{
    if (!last)
        return;
 
    // Recursive call
    rearrange(head, last->next);
 
    // (*head)->next will be set to NULL
    // after rearrangement.
    // Need not do any operation further
    // Just return here to come out of recursion
    if (!(*head)->next)
        return;
 
    // Rearrange the list until both head
    // and last meet or next to each other.
    if ((*head) != last && (*head)->next != last)
    {
        struct Node* tmp = (*head)->next;
        (*head)->next = last;
        last->next = tmp;
        *head = tmp;
    }
    else
    {
        if ((*head) != last)
            *head = (*head)->next;
        (*head)->next = NULL;
    }
}
 
// Drivers Code
int main()
{
    struct Node* head = newNode(1);
    head->next = newNode(2);
    head->next->next = newNode(3);
    head->next->next->next = newNode(4);
    head->next->next->next->next = newNode(5);
 
    // Print original list
    printlist(head);
 
    struct Node* tmp = head;
 
    // Modify the list
    rearrange(&tmp, head);
 
    // Print modified list
    printlist(head);
    return 0;
}

Producción:

1 ->2 ->3 ->4 ->5 
1 ->5 ->2 ->4 ->3

Complejidad de tiempo: O(n), donde n representa la longitud de la lista enlazada dada.
Espacio auxiliar: O(n), para pila recursiva donde n representa la longitud de la lista enlazada dada.

Consulte el artículo completo sobre Reorganizar una lista vinculada dada en el lugar. ¡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 *