Me pregunto si existe alguna lógica para revertir una lista enlazada individualmente usando solo dos punteros.
Se utiliza la siguiente para revertir la lista enlazada solo utilizando tres punteros a saber p
, q
, r
:
struct node {
int data;
struct node *link;
};
void reverse() {
struct node *p = first,
*q = NULL,
*r;
while (p != NULL) {
r = q;
q = p;
p = p->link;
q->link = r;
}
first = q;
}
¿Existe alguna otra alternativa para revertir la lista enlazada? ¿Cuál sería la mejor lógica para invertir una lista enlazada individualmente, en términos de complejidad temporal?
Respuestas:
¿Alguna alternativa? No, esto es tan simple como parece, y no hay una forma fundamentalmente diferente de hacerlo. Este algoritmo ya es O (n) tiempo, y no puede obtener más rápido que eso, ya que debe modificar cada nodo.
Parece que su código está en el camino correcto, pero no funciona en el formulario anterior. Aquí hay una versión funcional:
fuente
reverse()
función debería configurarse primero, creo. De lo contrario, el código original funcionó bien cuando se conectó a su prolijo arnés de prueba. Aún así, obtienes +1 de mí, pero una explicación de lo que consideras los 'errores obvios' mejoraría tu respuesta.Odio ser portador de malas noticias, pero no creo que su solución de tres puntos realmente funcione. Cuando lo usé en el siguiente arnés de prueba, la lista se redujo a un nodo, según el siguiente resultado:
No obtendrá una mejor complejidad de tiempo que su solución, ya que es O (n) y debe visitar cada nodo para cambiar los punteros, pero puede hacer una solución con solo dos punteros adicionales con bastante facilidad, como se muestra en el siguiente código:
Este código genera:
que creo que es lo que buscabas. De hecho, puede hacer esto ya que, una vez que lo haya cargado
first
en el puntero que atraviesa la lista, puede reutilizarlofirst
a voluntad.fuente
first
puntero en la lista vinculada permite que la solución use solo 2 punteros adicionales , pero aún son necesarios 3 punteros en total para esto.first
. La misma manera de la solución triple de la OP teníafirst
,p
,q
yr
.fuente
Aquí está el código para revertir una lista enlazada en C .
Y aquí está pegado a continuación:
fuente
Si. Estoy seguro de que puede hacer esto de la misma manera que puede intercambiar dos números sin usar un tercero . Simplemente eche los punteros a int / long y realice la operación XOR un par de veces. Este es uno de esos trucos de C que lo convierte en una pregunta divertida, pero no tiene ningún valor práctico.
¿Puede reducir la complejidad O (n)? No en realidad no. Solo use una lista doblemente vinculada si cree que va a necesitar el orden inverso.
fuente
Robert Sedgewick, " Algoritmos en C ", Addison-Wesley, 3ª edición, 1997, [Sección 3.4]
En caso de que no sea una lista cíclica, NULL es el último enlace.
fuente
Solo por diversión (aunque la optimización de recursividad de cola debería evitar que se coma toda la pila):
fuente
Para intercambiar dos variables sin el uso de una variable temporal,
la forma más rápida es escribirlo en una línea
Similar,
usando dos intercambios
solución usando xor
solución en una línea
Se utiliza la misma lógica para invertir una lista enlazada.
fuente
intptr_t
). Si bien es interesante, cambiar de esta manera no es óptimo en los sistemas modernos.Necesita un puntero de pista que rastreará la lista.
Necesitas dos consejos:
primer puntero para elegir el primer nodo. segundo puntero para elegir el segundo nodo.
Procesando :
Mover puntero de pista
Apunte el segundo nodo al primer nodo
Mueva el primer puntero un paso, asignando el segundo puntero a uno
Mover el segundo puntero un paso, asignando el puntero de pista al segundo
}
fuente
¿Qué tal el más legible?
fuente
Aquí hay una versión más simple en Java. Utiliza solo dos punteros
curr
yprev
fuente
Calcule la complejidad temporal del algoritmo que está utilizando ahora y debería ser obvio que no se puede mejorar.
fuente
No entiendo por qué es necesario devolver la cabeza ya que la estamos pasando como argumento. Estamos pasando el encabezado de la lista de enlaces y luego podemos actualizar también. A continuación se muestra una solución simple.
fuente
fuente
No, no se puede hacer nada más rápido que el actual O (n). Necesita alterar cada nodo, por lo que el tiempo será proporcional al número de elementos de todos modos y eso es O (n) que ya tiene.
fuente
El uso de dos punteros mientras se mantiene la complejidad de tiempo de O (n), el más rápido que se puede lograr, solo podría ser posible mediante el lanzamiento de números de punteros e intercambiando sus valores. Aquí hay una implementación:
fuente
Tengo un enfoque ligeramente diferente. Quería hacer uso de las funciones existentes (como insert_at (index), delete_from (index)) para invertir la lista (algo así como una operación de desplazamiento a la derecha). La complejidad sigue siendo O (n) pero la ventaja es un código más reutilizado. Eche un vistazo al método another_reverse () y déjeme saber lo que piensa.
fuente
fuente
fuente
Sí, hay una forma de usar solo dos punteros. Es decir, creando una nueva lista vinculada donde el primer nodo es el primer nodo de la lista dada y el segundo nodo de la primera lista se agrega al comienzo de la nueva lista y así sucesivamente.
fuente
Aquí está mi versión:
dónde
fuente
Estoy usando Java para implementar esto y el enfoque es un desarrollo impulsado por pruebas, por lo que también se adjuntan casos de prueba.
La clase Node que representa un solo nodo -
Clase de servicio que toma el nodo de inicio como entrada y lo reserva sin usar espacio adicional.
Y el caso de prueba que cubre el escenario anterior. Tenga en cuenta que necesita frascos junit. Estoy usando testng.jar; puedes usar cualquier cosa que te plazca ..
fuente
Un algoritmo simple si usa la lista vinculada como una estructura de pila:
El rendimiento puede verse afectado debido a la llamada de función adicional a add y malloc, por lo que los algoritmos de intercambio de direcciones son mejores, pero ese realmente crea una nueva lista para que pueda usar opciones adicionales como ordenar o eliminar elementos si agrega una función de devolución de llamada como parámetro al contrarrestar.
fuente
Aquí hay un enfoque simple pero ligeramente diferente en C ++ 11:
Salida aquí
fuente
A continuación se muestra una implementación con 2 punteros (head yr)
fuente
sizeof(size_t) < sizeof(ListNode*)
... debes usarstd::uintptr_t
.aquí hay una pequeña solución simple ...
fuente
Puede solucionar este problema con la ayuda de un solo puntero adicional, que debe ser estático para la función inversa. Está en complejidad O (n).
fuente
Como alternativa, puede utilizar la recursividad
fuente
fuente
fuente