2011-12-31 6 views
21

Estoy intentando invertir una lista vinculada. Este es el código que se me ocurrió:Inversión de la lista vinculada única en C#

public static void Reverse(ref Node root) 
{ 
     Node tmp = root; 
     Node nroot = null; 
     Node prev = null; 

     while (tmp != null) 
     { 
      //Make a new node and copy tmp 
      nroot = new Node();  
      nroot.data = tmp.data; 

      nroot.next = prev; 
      prev = nroot; 
      tmp = tmp.next; 
     } 
     root = nroot;    
    } 

Está funcionando bien. Me preguntaba si sería posible evitar la creación de un nuevo nodo. Me gustaría tener sugerencias sobre esto.

+2

Por qué están implementando una colección personalizada para esto? ¿No funciona ninguna de las opciones disponibles en el espacio de nombres 'System.Collections' para sus requisitos? –

+8

Estoy aprendiendo y preparándome para una entrevista. – Nemo

+0

¿Qué espacio de nombres es Nodo? –

Respuesta

36
Node p = root, n = null; 
while (p != null) { 
    Node tmp = p.next; 
    p.next = n; 
    n = p; 
    p = tmp; 
} 
root = n; 
2

¿Por qué no tener simplemente el punto de cabeza en la cola, el punto de cola en la cabeza, y pasar por la lista invirtiendo la dirección en la cual los puntos previos?

Si no está utilizando una cabeza y una cola, simplemente revise la lista invirtiendo las relaciones previas, y luego diríjase a la que tenía un valor nulo anterior cuando llegó a ella.

+0

¿cómo se puede hacer en O (N)? – Nemo

+0

Eso sería O (N). –

6

No necesita hacer una copia. Algunos pseudo código:

prev = null; 
current = head; 
next = current->next; 

(while next != null) 
    current->next=prev 
    prev=current 
    current=next 
    next=current->next 
45

Esa pregunta se hace mucho. Cuando me lo preguntaron en mis entrevistas hace muchos años, razoné de la siguiente manera: una lista con un solo enlace es esencialmente una pila. Revirtiendo una lista enlazada, por tanto, es una operación trivial en pilas:

newList = emptyList; 
while(!oldList.IsEmpty()) 
    newList.Push(oldList.Pop()); 

Ahora todo lo que tiene que hacer es poner en práctica IsEmpty y Push y Pop, que son una o dos líneas como máximo.

Lo escribí en unos veinte segundos y el entrevistador parecía algo perplejo en ese momento. Creo que esperaba que yo tomara unos veinte minutos para hacer unos veinte segundos de trabajo, lo que siempre me ha parecido extraño.

+0

+1 - pregunta: ¿No debería asegurarse también de que '! =' Esté sobrecargado, por lo que cuando 'oldList' está vacío, se registra como" igual que '' emptyList'? –

+0

@AdamRackis: Claro. Cambie a 'while (! OldList.IsEmpty())' si lo prefiere. Esto es pseudocódigo, no una implementación real en ningún idioma. –

+0

Gracias @Eric - su pseudocódigo parece ser sintacticamente perfecto C#, (lo cual no es sorprendente) así que tuve que preguntar :) –

-2

La definición de la referencia no es necesario porque si se hace el nodo como un tipo de referencia, que está bien hacer:

public static void Reverse(Node root) 

Además, la belleza de la pregunta de la entrevista es menor consumo de memoria y en su lugar inversión. Tal vez también se le pida una forma recursiva de hacerlo. Hace

1
public Node ReverseList(Node cur, Node prev) 
    { 
     if (cur == null) // if list is null 
      return cur; 

     Node n = cur.NextNode; 
     cur.NextNode = prev; 
     return (n == null) ? cur : ReverseList(n, cur); 
    } 
+0

cur parece ser la raíz - ¿qué es anterior? – fubo

4

años me perdí una posición desarrollador ASP.NET MVC hipster-LA-entretenimiento de la compañía porque no podía responder a esta pregunta :((Es una manera de eliminar a los mayores no en la ciencia informática.) así que estoy avergonzado de admitir que me tomó demasiado tiempo para resolver esto en LINQPad según los días reales LinkedList<T>:.

var linkedList = new LinkedList<int>(new[]{1,2,3,4,5,6,7,8,9,10}); 
linkedList.Dump("initial state"); 

var head = linkedList.First; 
while (head.Next != null) 
{ 
    var next = head.Next; 
    linkedList.Remove(next); 
    linkedList.AddFirst(next.Value); 
} 

linkedList.Dump("final state"); 

el sólo lectura LinkedListNode<T>.Next propiedad es lo que hace LinkedList<T> tan importante aquí (no comp -la gente de ciencia se anima a estudiar la historia de las estructuras de datos --- se supone que debemos hacernos la pregunta, ¿dónde está el linked list vienen de --- ¿por qué existe?)

+1

Como usted, perdí una posición de desarrollador de ASP.NET MVC la semana pasada debido a la misma pregunta sobre la inversión de una lista vinculada :( –

+1

¡Bueno! Aunque revertir una lista vinculada es un problema general, implementarlo C# es diferente y complicado en comparación con decir C++ o Java porque el nodo de C# no permite el ajuste siguiente. Por lo tanto, tienes que volver a la configuración siguiente y pensar en eliminarlo. –

0

Aquí hay un código de muestra para revertir una lista vinculada.

usando Sistema;

class Program 
{ 
    static void Main(string[] args) 
    { 
     LinkItem item = generateLinkList(5); 
     printLinkList(item); 
     Console.WriteLine("Reversing the list ..."); 
     LinkItem newItem = reverseLinkList(item); 
     printLinkList(newItem); 
     Console.ReadLine(); 
    } 

    static public LinkItem generateLinkList(int total) 
    { 
     LinkItem item = new LinkItem(); 
     for (int number = total; number >=1; number--) 
     { 
      item = new LinkItem 
      { 
       name = string.Format("I am the link item number {0}.", number), 
       next = (number == total) ? null : item 
      }; 
     } 
     return item; 
    } 

    static public void printLinkList(LinkItem item) 
    { 
     while (item != null) 
     { 
      Console.WriteLine(item.name); 
      item = item.next; 
     } 
    } 

    static public LinkItem reverseLinkList(LinkItem item) 
    { 
     LinkItem newItem = new LinkItem 
     { 
      name = item.name, 
      next = null 
     }; 

     while (item.next != null) 
     { 
      newItem = new LinkItem 
      { 
       name = item.next.name, 
       next = newItem 
      }; 

      item = item.next; 
     } 

     return newItem; 
    } 
} 

class LinkItem 
{ 
    public string name; 
    public LinkItem next; 
} 
0

Complexity O (n + m).Suponiendo que la cabeza está el nodo de inicio:

List<Node>Nodes = new List<Node>(); 
Node traverse= root; 
while(traverse!=null) 
{  
     Nodes.Add(traverse); 
     traverse = traverse.Next; 

} 

int i = Nodes.Count - 1;  
root = Nodes[i]; 
for(; i>0; i--) 
{ 
    Nodes[i].Next = Nodes[i-1]; 
} 
Nodes[0].Next=null; 
0

lista enlazada reversión recursiva

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace ReverseLinkedList 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Node head = null; 
      LinkedList.Append(ref head, 25); 
      LinkedList.Append(ref head, 5); 
      LinkedList.Append(ref head, 18); 
      LinkedList.Append(ref head, 7); 

      Console.WriteLine("Linked list:"); 
      LinkedList.Print(head); 

      Console.WriteLine(); 
      Console.WriteLine("Reversed Linked list:"); 
      LinkedList.Reverse(ref head); 
      LinkedList.Print(head); 

      Console.WriteLine(); 
      Console.WriteLine("Reverse of Reversed Linked list:"); 
      LinkedList.ReverseUsingRecursion(head); 
      head = LinkedList.newHead; 
      LinkedList.PrintRecursive(head); 
     } 

     public static class LinkedList 
     { 
      public static void Append(ref Node head, int data) 
      { 
       if (head != null) 
       { 
        Node current = head; 
        while (current.Next != null) 
        { 
         current = current.Next; 
        } 

        current.Next = new Node(); 
        current.Next.Data = data; 
       } 
       else 
       { 
        head = new Node(); 
        head.Data = data; 
       } 
      } 

      public static void Print(Node head) 
      { 
       if (head == null) return; 
       Node current = head; 
       do 
       { 
        Console.Write("{0} ", current.Data); 
        current = current.Next; 
       } while (current != null); 
      } 

      public static void PrintRecursive(Node head) 
      { 
       if (head == null) 
       { 
        Console.WriteLine(); 
        return; 
       } 
       Console.Write("{0} ", head.Data); 
       PrintRecursive(head.Next); 
      } 

      public static void Reverse(ref Node head) 
      { 
       if (head == null) return; 
       Node prev = null, current = head, next = null; 
       while (current.Next != null) 
       { 
        next = current.Next; 
        current.Next = prev; 
        prev = current; 
        current = next; 
       } 
       current.Next = prev; 
       head = current; 
      } 

      public static Node newHead; 

      public static void ReverseUsingRecursion(Node head) 
      { 
       if (head == null) return; 
       if (head.Next == null) 
       { 
        newHead = head; 
        return; 
       } 

       ReverseUsingRecursion(head.Next); 
       head.Next.Next = head; 
       head.Next = null; 
      } 
     } 

     public class Node 
     { 
      public int Data = 0; 
      public Node Next = null; 
     } 
    } 
} 
Cuestiones relacionadas