Listas Rafael Palacios May/2005 Descripción Las listas son estructuras de datos parecidas a los vectores ☺ Aprovechan la memoria mejor que los vectores ☺ Facilitan las operaciones de inserción y borrado No existe acceso directo a los datos, sino que debe recorrerse la lista desde el principio (como si fuese un archivo de texto) Definición typedef struct persona { char nombre[25]; char apellidos[50]; int edad; struct persona *siguiente; } t_persona; Estructura que contiene un puntero a otra estructura del mismo tipo Listas ~ vectores typedef struct persona { char nombre[25]; char apellidos[50]; int edad; } t_persona; int main(void) { t_persona *vec; int n; //longitud del vector : : : typedef struct persona { char nombre[25]; char apellidos[50]; int edad; struct persona *siguiente; } t_persona; int main(void) { t_persona *inicio; : : : Listas ~ vectores Vector: posiciones de memoria consecutivas nombre vec apellidos * edad n=3 nombre apellidos inicio * nombre nombre edad apellidos apellidos nombre edad edad apellidos siguiente * siguiente * edad Lista: posiciones de memoria variables nombre apellidos edad siguiente * NULL Asignación de vectores typedef struct persona { char nombre[25]; char apellidos[50]; int edad; } t_persona; t_persona Lectura(void); int main(void) { t_persona *vec; //puntero para construir el vector int n; //longitud del vector int i; //contador n=3; vec=(t_persona *)calloc(n,sizeof(t_persona)); if (vec==NULL) { printf("Error de memoria.\n"); } else { for(i=0; i<n; i++) { vec[i]=Lectura(); } : : Asignación de listas typedef struct persona { char nombre[25]; char apellidos[50]; int edad; struct persona *siguiente; } t_persona; t_persona Lectura(void); int main(void) { t_persona *inicio; //puntero al principio de la lista t_persona *aux; //puntero auxiliar, para moverme por la lista int i; //contador int ok; //control de errores inicio=(t_persona *)calloc(1,sizeof(t_persona)); if (inicio==NULL) { printf("Error de memoria.\n"); } else { aux=inicio; i=0; ok=0; do { *aux=Lectura(); aux->siguiente=(t_persona *)calloc(1,sizeof(t_persona)); if (aux->siguiente==NULL) { printf("Error de memoria\n"); ok=0; } else { aux=aux->siguiente; //Paso al siguiente elemento i++; } }while(ok==1 && i<3); : : Operaciones básicas: Mostrar la lista Imprimir todos los elementos (vector) void Mostrar(t_persona *vec, int n) { int i: //contador for(i=0; i<n; i++) { printf("%s %s: %d años\n", vec[i].nombre, vec[i].apellidos, vec[i].edad); } printf("Fin.\n"); } Vectores: bucle for Imprimir todos los elementos (listas) void Mostrar(t_persona *aux) { while (aux!=NULL) { printf("%s %s: %d años\n", aux->nombre, aux->apellidos, aux->edad); aux=aux->siguiente; } printf("Fin.\n"); } void Mostrar(t_persona *aux) { if (aux==NULL) { printf("Fin.\n"); } else { printf("%s %s: %d años\n", aux->nombre, aux->apellidos, aux->edad); Mostrar(aux->siguiente); } } Paso al siguiente elemento Listas: con bucle while Listas: con función recursiva Recorrer Listas inicio aux * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre apellidos aux=inicio; edad siguiente * NULL Recorrer Listas inicio aux * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre apellidos edad aux=aux->siguiente; siguiente * NULL Recorrer Listas inicio aux * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre apellidos 2 aux=aux->siguiente; edad siguiente * NULL Recorrer Listas inicio aux * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre apellidos 3 aux=aux->siguiente; edad siguiente * NULL Imprimir al revés (listas) Mostrar de principio a final void Mostrar(t_persona *aux) { if (aux==NULL) { printf("Fin.\n"); } else { printf("%s %s: %d años\n", aux->nombre, aux->apellidos, aux->edad); Mostrar(aux->siguiente); } } Mostrar de final a principio void Mostrar(t_persona *aux) { if (aux==NULL) { printf("Los datos son:\n"); } else { Mostrar(aux->siguiente); printf("%s %s: %d años\n", aux->nombre, aux->apellidos, aux->edad); } } Al cambiar el orden de la llamada recursiva cambia el comportamiento de la función Operaciones básicas: Insertar un elemento Insertar un elemento (1/4) aux new * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre Código: new->siguiente = aux->siguiente; aux->siguiente = new; apellidos edad siguiente * Insertar un elemento (2/4) aux new * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre Código: new->siguiente = aux->siguiente; aux->siguiente = new; apellidos edad siguiente * Insertar un elemento (3/4) aux new * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre Código: new->siguiente = aux->siguiente; aux->siguiente = new; apellidos edad siguiente * Insertar un elemento (4/4) aux new * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * nombre Código: new->siguiente = aux->siguiente; aux->siguiente = new; apellidos edad siguiente * Operaciones básicas: Borrar un elemento Borrar un elemento (1/5) Quiero borrar este elemento aux aux2 * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * Código: aux2 = aux->siguiente; aux->siguiente = aux2->siguiente; free(aux2); Borrar un elemento (2/5) Quiero borrar este elemento aux aux2 * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * Código: aux2 = aux->siguiente; aux->siguiente = aux2->siguiente; free(aux2); Borrar un elemento (3/5) Quiero borrar este elemento aux aux2 * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * Código: aux2 = aux->siguiente; aux->siguiente = aux2->siguiente; free(aux2); Borrar un elemento (4/5) BORRADO ! aux aux2 * * nombre nombre apellidos apellidos edad edad siguiente * siguiente * Código: aux2 = aux->siguiente; aux->siguiente = aux2->siguiente; free(aux2); Borrar un elemento (5/5) aux nombre * apellidos aux2 * edad siguiente * ? Código: aux2 = aux->siguiente; aux->siguiente = aux2->siguiente; free(aux2);