Este problema se puede resolver con dos enfoques distintos. El primero consiste en modificar la lista enlazada original. Utilizamos dos punteros: uno para recorrer la lista y otro para mantener el nodo anterior.
struct Nodo* eliminarElementos(struct Nodo* cabeza, int valor) {
struct Nodo* anterior = NULL;
struct Nodo* actual = cabeza;
while(actual)
{
if(actual->valor == valor)
{
if(anterior == NULL)
{
cabeza = cabeza->siguiente;
actual = actual->siguiente;
}
else
{
struct Nodo* temp = actual;
actual = actual->siguiente;
free(temp);
anterior->siguiente = actual;
}
}
else
{
anterior = actual;
actual = actual->siguiente;
}
}
return cabeza;
}
El segundo enfoque utiliza la técnica de inserción en la cola para crear una nueva lista enlazada:
struct Nodo* eliminarElementos(struct Nodo* cabeza, int valor) {
struct Nodo* nuevacabeza = NULL, *cola = NULL;
struct Nodo* actual = cabeza;
while(actual)
{
if(actual->valor == valor)
{
actual = actual->siguiente;
}
else
{
if(nuevacabeza == NULL)
{
nuevacabeza = actual;
cola = nuevacabeza;
}
else
{
cola->siguiente = actual;
cola = cola ->siguiente;
}
actual = actual->siguiente;
}
}
if(cola)
cola->siguiente = NULL;
return nuevacabeza;
}
Invertir una Lista Enlazada
Este problema tiene dos soluciones comunes. La primera utiliza tres punteros para ivnertir los enlaces:
struct Nodo* invertirLista(struct Nodo* cabeza) {
if(cabeza == NULL)
return NULL;
struct Nodo* previo = NULL;
struct Nodo* actual = cabeza;
struct Nodo* siguiente = NULL;
while(actual != NULL)
{
siguiente = actual->siguiente;
actual->siguiente = previo;
previo = actual;
actual = siguiente;
}
return previo;
}
La segunda solución utiliza el método de inserción en la cabeza:
struct Nodo* invertirLista(struct Nodo* cabeza) {
struct Nodo* nuevacabeza = NULL;
struct Nodo* actual = cabeza;
while(actual)
{
struct Nodo* temp = actual->siguiente;
actual->siguiente = nuevacabeza;
nuevacabeza = actual;
actual = temp;
}
return nuevacabeza;
}
Encontrar el Nodo Medio de una Lista Enlazada
Este problema se resuelve eficientemente con el algoritmo de punteros rápidos y lentos:
struct Nodo* nodoMedio(struct Nodo* cabeza) {
struct Nodo* rapido = cabeza;
struct Nodo* lento = cabeza;
while(rapido && rapido->siguiente)
{
rapido = rapido->siguiente->siguiente;
lento = lento->siguiente;
}
return lento;
}
Encontrar el K-ésimo Nodo desde el Final
Utilizando una modificación del algoritmo de punteros rápidos y lentos:
struct Nodo* encontrarKDesdeFinal(struct Nodo* pListHead, int k) {
struct Nodo*lento = pListHead;
struct Nodo*rapido = pListHead;
while(k-- > 0)
{
if(rapido == NULL)
return NULL;
rapido = rapido->siguiente;
}
while(rapido)
{
rapido = rapido->siguiente;
lento = lento->siguiente;
}
return lento;
}
Combinar Dos Listas Enlazadas Ordenadas
Este problema se resuelve comparando nodos de ambas listas y construyendo una nueva lista enlazada ordenada:
struct Nodo* combinarDosListas(struct Nodo* lista1, struct Nodo* lista2) {
if(lista1 == NULL && lista2 == NULL)
{
return NULL;
}
struct Nodo* actual1 = lista1;
struct Nodo* actual2 = lista2;
struct Nodo* nuevacabeza = NULL;
struct Nodo* cola = NULL;
while(actual1 && actual2)
{
if(actual1->valor < actual2->valor)
{
if(nuevacabeza == NULL)
{
nuevacabeza = cola = actual1;
}
else
{
cola->siguiente = actual1;
cola = cola->siguiente;
}
actual1 = actual1->siguiente;
}
else
{
if(nuevacabeza == NULL)
{
nuevacabeza = cola = actual2;
}
else
{
cola->siguiente = actual2;
cola = cola->siguiente;
}
actual2 = actual2->siguiente;
}
}
// Agregar los nodos restantes
if(actual1)
cola->siguiente = actual1;
else if(actual2)
cola->siguiente = actual2;
return nuevacabeza;
}
La clave para resolver estos problemas es practicar con diagramas y recorrer manualmente el código con diferentes casos de prueba.