"...pero no se para que puede servir..."
Suele usarse para listas de datos, donde cada elemento puede relacionarse con cualquier otro; lo mas facil es que un elemento se relacione con el siguiente de forma que obtienes una lista enlazada simple.
Supongamos que tienes una novia en cada pueblo, y quieres crear una lista para no confundirte :)
Primero declaras una struct que identifica el elemento y la relacion que tiene con cualquier otro (u otros):
Código C:
Ver originalstruct NOVIA {
char nombre[20];
char ciudad[50];
char fecha_cita[20];
struct NOVIA *siguiente;
};
Ahora declaras una lista; una lista es un simple puntero inicialmente nulo:
Luego pasas a implementar la lista; traducido significa que reservas memoria para una struct (es decir que obtienes un puntero a una direccion de memoria) y la envias a la posicion de la lista que quieras. Habitualmente si la lista es nula se asigna el primer elemento como base de la lista, y los siguientes se asignan como elemento 'siguiente' del ultimo elemento de la lista:
Código C:
Ver originalstruct NOVIA *novia;
novia
= malloc(sizeof(struct NOVIA
));sprintf(novia
->nombre
, "samanta fox"); novia->siguiente = 0;
amorios = novia;
novia
= malloc(sizeof(struct NOVIA
));sprintf(novia
->nombre
, "quin sea"); novia->siguiente = 0;
amorios->siguiente = novia;
Ok, ya se que el ejemplo es un poco tonto, pero ya te has quedado con la idea de que va eso de las listas.
Otro punto importante de las listas es liberar la memoria usada, es decir que para cada malloc necesitas un free.
Todo esto suele serializarse, es decir que tienes una funcion que reserva memoria para un elemento, busca en la lista la ultima posicion y añade el nuevo elemento, luego tienes otra que busca algun dato, luego otras que hacen lo que quieras, y una ultima funcion que libera la memoria usada.
Esta es la declaracion basica de una lista simple (ahora sin novias):
Código C:
Ver original//soporte de datos
struct DATO {
int numero;
struct DATO *sig;
};
void nuevo(struct DATO **lista, int numero) {
struct DATO *dato, *ptr;
//reservo memoria para el nuevo dato
dato
= malloc(sizeof(struct DATO
)); dato->numero = numero;
dato->sig = 0;
//si la lista no existe, se asigna el nuevo dato como base
if(!(ptr = *lista)) {
*lista = dato;
}
else {
//si la lista existe, se busca el ultimo elemento y se asigna el nuevo como siguiente
while(ptr->sig) {
ptr = ptr->sig;
}
ptr->sig = dato;
}
}
void muestra(struct DATO *lista) {
struct DATO *ptr;
//simplemente recorre la lista
ptr = lista;
while(ptr) {
ptr = ptr->sig;
}
}
void vacia(struct DATO **lista) {
struct DATO *ptr, *sig;
ptr = *lista;
while(ptr) {
//guarda la posicion del siguiente para recuperarla despues de eliminar el actual
sig = ptr->sig;
//ahora recuperas la posicion guardada antes
//en este momento ptr->siguiente ya no está dentro del bloque de memoria accesible
//y por eso necesitas el recordatorio para seguir
ptr = sig;
}
*lista = 0;
}
Ahora las llamadas:
Código C:
Ver originalstruct DATO *lista;
int q;
//confirmas la lista como nula
lista = 0;
//la llenas
for(q = 0; q < 5; q++) {
nuevo(&lista, q);
}
//mostrar
muestra(lista);
//y la vacias
vacia(&lista);
Dos cosas a tener en cuenta: cuando trabajas com memoria dinamica el s.o. suele asignarte bloques de memoria reutilizados, es decir que pueden contener cualquier cosa, es decir que si declaras un entero no valdrá 0 por defecto sino que valdrá el equivalente a entero de la posicion de memoria que se le asigna, por eso todo lo que reservas y quieres que sea nulo tienes que asignarle manualmente nulo; es el caso de cuando inicias la lista a nulo (0), o de cuando creas el nuevo elemento y necesitas que el siguiente elemento sea nulo.
La otra cosa a tener en cuenta: siempre que trabajas con listas tienes que evitar trabajar directamente sobre la base a menos que tengas una forma de restaurar el puntero a la posicion de memoria inicial (cuando pierdes el puntero de la base se produce una peridia de memoria o memory leak, es decir que durante toda la aplicacion ese bloque de memoria será inaccesible y no reutilizable).
Este ejemplo es lo mas basico, las listas se pueden complicar mas. Puedes ordenarlas (intercambiando los punteros), puedes quitar elementos que hay enmedio, puedes reasignar valores, etc...
Esto de las listas es muy interesante y bonito de programar, ademas puedes implementarlas en cualquier aplicacion.
Saludos
vosk