Listas encadenadas o Linked List en C
Buenas! Como dije voy a escribir una serie de artículos sobre C según encuentre cosas que me parezcan interesantes o útiles.
Una de estas cosas útiles son las listas encadenadas. Es una estructura de datos que en C se puede representar mediante un struct y consiste en un "registro" de los campos que se deseen (generalmente uno) más otro que es un puntero que apunta al siguiente registro, y asi sucesivamente. Hay varios tipos de listas encadenadas que podéis ver en el enlace que os dejé.
Pues procediendo a realizar un ejemplo imaginemos que queremos guardar una lista de alumnos con su nombre, apellidos y DNI. Nos quedaría un programa así:
/*
* Autor: Sergio C. <skgsergio@gmail.com>
*
* Licencia: GPL v3 - http://www.gnu.org/licenses/gpl-3.0.html
*/
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/* Estructura que va a definir a un alumno */
struct alumno_st {
char *nombre;
char *apellidos;
int dni;
/* Puntero para indicar cual es el alumno siguiente en la lista */
struct alumno_st *siguiente;
};
/* Basicamente es un renombramiento para que en vez de definir
* variables o punteros así "struct alumno_st *mi_alumno" podamos
* definirlos así "alumno *mi_alumno".
*/
typedef struct alumno_st alumno;
/* Punteros para indicar el primer y ultimo elemento de la lista */
alumno *inicial = NULL;
alumno *ultimo = NULL;
/* Añadir un alumno */
void aniadir() {
alumno *ptr;
/* Reservamos memoria para esta estructura */
if ((ptr = (alumno *) malloc(sizeof(alumno)))) {
char linea[25];
/* Leemos el nombre y lo guardamos */
printf("Nombre:\t\t");
fgets(linea,sizeof(linea),stdin);
ptr->nombre = strdup(linea);
/* Leemos los apellidos y lo guardamos */
printf("Apellidos:\t");
fgets(linea,sizeof(linea),stdin);
ptr->apellidos = strdup(linea);
/* Leemos el DNI y lo guardamos */
printf("DNI:\t\t");
fgets(linea,sizeof(linea),stdin);
sscanf(linea,"%d",&ptr->dni);
/* Ajustamos los punteros */
if (!inicial)
inicial = ptr;
if (ultimo)
ultimo->siguiente = ptr;
ultimo = ptr;
/* Salto de linea */
printf("\n");
} else {
fprintf(stderr,"Error al reservar espacio en memoria.");
}
}
/* Eliminar un alumno */
void eliminar() {
if (inicial) {
char linea[25];
int dni;
int buscar = 1;
alumno *aux = inicial;
alumno *ant = NULL;
/* Pedimos el DNI */
printf("DNI del alumno a eliminar\n> ");
fgets(linea,sizeof(linea),stdin);
sscanf(linea,"%d",&dni);
/* Buscamos el alumno */
while (buscar && aux) {
if (aux->dni == dni) {
/* Modificamos los punteros */
if (aux->siguiente) {
/* Si hay un siguiente y un anterior
* ponemos el campo siguiente del anterior
* puntando al siguiente del que vamos a borrar.
* Si no hay un anterior pero siguiente sí
* ponemos el puntero inicial apuntando al siguiente.
*/
if (ant)
ant->siguiente = aux->siguiente;
else
inicial = aux->siguiente;
} else {
/* Si no hay un siguiente pero si un anterior
* ponemos su puntero siguiente del anterior
* a null y ponemos en el puntro ultimo el anterior.
* Si no hay siguiente ni anterior ponemos los punteros
* inicial y ultimo a null.
*/
if (ant) {
ultimo = ant;
ant->siguiente = NULL;
} else {
inicial = NULL;
ultimo = NULL;
}
}
/* Liberamos la memoria que ocupaba esta estructura */
free(aux);
buscar = 0;
} else {
ant = aux;
aux = aux->siguiente;
}
}
/* Emitimos el resultado de la operación */
if (buscar)
printf("No se ha encontrado un alumno con dni %d\n\n",dni);
else
printf("Se ha borrado correctamente el alumno con dni %d\n\n",dni);
} else {
printf("No hay alumnos registrados.\n\n");
}
}
/* Mostrar alumnos */
void mostrar() {
if (inicial) {
alumno *aux = inicial;
int num = 1;
while (aux) {
printf("Alumno %d:\n",num);
/* Imprimimos cada campo */
printf("\tNombre:\t\t%s\n",aux->nombre);
printf("\tApellidos:\t%s\n",aux->apellidos);
printf("\tDNI:\t\t%d\n\n",aux->dni);
/* Comprobamos si hemos llegado al ultimo */
if (aux != ultimo)
aux = aux->siguiente;
else
aux = NULL;
num++;
}
} else {
printf("No hay alumnos registrados.\n\n");
}
}
/* Menu principal */
int main() {
int tmp;
system("clear");
do {
char linea[25];
/* Mostramos las opciones */
printf("1: Añadir alumno\t3: Mostrar alumnos\n");
printf("2: Eliminar alumno\t4: Salir del programa\n\n");
/* Leemos la opción */
printf("> ");
fgets(linea,sizeof(linea),stdin);
if(!sscanf(linea,"%d",&tmp)) tmp = 0;
/* Analizamos los casos */
system("clear");
switch (tmp) {
case 1:
aniadir();
break;
case 2:
eliminar();
break;
case 3:
mostrar();
break;
case 4:
break;
default:
printf("Opción incorrecta.\n\n");
break;
}
} while (tmp != 4);
return 0;
}
Al final me ha quedado un programa mas grande de lo que buscaba pero así os entretenéis en toquetearlo y hacer pruebas con el código y demás. Cualquier duda es bienvenida excepto si es para decirme que no funciona en Windows ya que lo he programado en Mac OS X (XNU basado en Match + BSD) y probado en CentOS (Linux) pensando principalmente en que funcione en sistemas Unix.
Nota:
No pretendo crear un manual de programación por lo que los artículos que hago no van a decir un while se hace así o un struct se hace de tal forma, considero que la mejor forma de aprender un lenguaje es consultar los libros que la gente suele recomendar y experimentar con el.
Si has llegado aquí buscando resolver practicas de tu universidad o similar y no te interesa C quizás no es el mejor sitio ya que yo no voy a hacer las practicas de nadie (si, he recibido comentarios y emails pidiéndome resolver practicas en ADA)
¿Te gustó este artículo?
Aún no hay trackbacks.
Enlaces
- Barrapunto
- Blog de Yclan
- Brave New World
- Cats’ Paradise
- Eien-no-Ai
- Fotos en Flickr
- skgsergio's GitHub
- Wikimanga
Categorías
- ADA
- C/C++
- Consolas
- General
- IRC
- Java
- Linux
- Mac OS X
- Otros
- PHP
- Programación
- Sistemas
- Unix en general
- Vida-Real
Comentarios recientes
- Anónimo en El rey de los proyectos inacabados…
- NeoFtw en Reflexiones sobre la sociedad
- Antonio en Listas encadenadas o Linked List en C
- Ingeniero24 en Procedures con prametros in, out e in out
- Rarok en Reflexiones sobre la sociedad

4 junio, 2010 - 23:19
Quién querría suspender tan descaradamente que te pidió que desarrolles sus prácticas? :|
Usando5 junio, 2010 - 12:32
Uhm… precisamente me lo pedía por que no quería suspender, tu comentario suena a critica hacia mi forma de programar… A lo que me refería en el post en concreto era a esto.
A no ser que me equivoque tu “quien querría suspender tan descaradamente que te pidió…” suena a que si se lo hubiera resuelto yo hubiera suspendido si es así para tu información ADA se me daba bastante bien pero es un coñazo de lenguaje y C es un juguete. si no lo decías con esta intención pues lo siento, pero el motivo de mis post es ayudar a la gente, si puedes hacerlo mejor tu pues a ver si es verdad, te ofrezco publicar un post sobre algo complejo en C dándote todo el crédito de ello.
Usando24 noviembre, 2010 - 08:09
gracias por el esfuerzo. Hace falta gente que busque servir a los que sabemos poco.
Usando