AprenderC
← Todas las lecciones

Una lista que se mantiene ordenada

Si cada dato entra en su sitio, la lista nunca hay que ordenarla.

1Por qué

En la lección 17 añadías siempre por delante, y la lista salía al revés del orden en que entraban los datos. Sirve, pero para casi nada de lo que se pide en un taller.

Para que salga ordenada hay que meter cada dato en su sitio: avanzar hasta encontrar el primero que sea mayor, y colarse justo antes. El problema es lo que eso significa en C.

Colar un nodo entre dos exige cambiar el sig del anterior. Y si el sitio resulta ser el principio, no hay anterior: hay que cambiar la cabeza. Escrito de la forma obvia, salen dos casos distintos y un if para separarlos — que es donde se cuelan la mitad de los errores.

Hay una forma de que sea un solo caso, y es bonita: en vez de ir guardando el nodo anterior, se va guardando la dirección del puntero que hay que cambiar. Al principio esa dirección es la de la cabeza; después, la del sig de cada nodo. Los dos son lo mismo —un puntero a nodo que hay que reapuntar— y por eso el código no necesita distinguirlos.

Es la idea de la lección 21 usada a fondo. Si p = &(*p)->sig te marea, léelo despacio: p deja de apuntar a la cabeza y pasa a apuntar al sig del primero. Sigue siendo la dirección del puntero que toca cambiar.

2Míralo andar

Este programa funciona. Léelo, y después ejecútalo sin cambiar nada.

#include <stdio.h>
#include <stdlib.h>
typedef struct Nodo {
int valor;
struct Nodo *sig;
} Nodo;
void insertar(Nodo **p, int x)
{
while (*p != NULL && (*p)->valor < x)
p = &(*p)->sig;
Nodo *n = malloc(sizeof(Nodo));
n->valor = x;
n->sig = *p;
*p = n;
}
int main(void)
{
Nodo *lista = NULL;
insertar(&lista, 5);
insertar(&lista, 2);
insertar(&lista, 9);
for (Nodo *q = lista; q != NULL; q = q->sig)
printf("%d ", q->valor);
printf("\n");
while (lista != NULL)
{
Nodo *s = lista->sig;
free(lista);
lista = s;
}
return 0;
}

3Ahora tú

A esta inserción le falta avanzar, así que mete todo al principio. Escribe la línea que avanza, para que salga: 2 5 9

#include <stdio.h>
#include <stdlib.h>
typedef struct Nodo {
int valor;
struct Nodo *sig;
} Nodo;
void insertar(Nodo **p, int x)
{
while (*p != NULL && (*p)->valor < x)
{
}
Nodo *n = malloc(sizeof(Nodo));
n->valor = x;
n->sig = *p;
*p = n;
}
int main(void)
{
Nodo *lista = NULL;
insertar(&lista, 5);
insertar(&lista, 2);
insertar(&lista, 9);
for (Nodo *q = lista; q != NULL; q = q->sig)
printf("%d ", q->valor);
printf("\n");
while (lista != NULL)
{
Nodo *s = lista->sig;
free(lista);
lista = s;
}
return 0;
}

↖︎ Tu línea va aquí. Tiene que mover p al puntero siguiente, no al nodo siguiente.

Ejecutar

Lo que dice tu programa

↖︎ Escribe tu parte y dale a Ejecutar

Qué pasó

Aquí te aviso si tu programa hace algo raro.

    4Qué guarda tu programa

    Memoria

    ↖︎ Ejecuta el programa para ver qué pasa por dentro