Listas dinámicas en C Introducción a la Computación Clase 19 Patricia Borensztejn Vectores estáticos y dinámicos • Ya hemos visto como crear estáticamente vectores de tamaño fijo: – int vector[100] • Y como crear vectores dinámicos, es decir cuyo tamaño lo especificamos en tiempo de ejecución: – int *vector – vector=malloc(tamaño*sizeof(tipo)) Listas enlazadas en C • Ahora lo que queremos es armar un vector añadiendo un elemento por vez, en la medida que lo vayamos necesitando. • Queremos algo asi como lo que hace Python, • ¿Como resolverlo en C? Listas enlazadas • Tendremos que ir agregando elementos que contengan un puntero al próximo elemento: • O sea que, cada elemento está formado por : – Un elemento del tipo deseado (int) – Un puntero al próximo, o null si es el último. Listas enlazadas • Cada elemento, que llamaremos «nodo» estará definido por un struct (o registro) así: • Hay dos elementos en el registro: – Un elemento llamado info de tipo entero – Un puntero al próximo nodo • ¡Observemos que hay un toque de recursividad en la definición! Listas enlazadas • Definimos la lista inicialmente vacía así: Adición de nodos • Queremos agregar un nodo a la lista vacía : Operador -> • El operador -> reemplaza el uso del operador * junto con el operador . • lista no es una variable de tipo stuct, sino una variable de tipo puntero a struct. • Para acceder al campo info del struct nodo, debemos hacer: – *(lista).info=8 O bien: – lista->info=8 • El operador ->se llama selector indirecto, mientras que el operador . se llama selector directo Añadimos otro elemento por la cabeza • Queremos añadir otro elemento a la lista: ¡Así no! Añadimos un elemento por la cabeza • Necesitamos una variable auxiliar aux=lista; lista=malloc(sizeof(struct Nodo)); lista->info=3 lista->sig=aux Añadimos elementos por la cola • Ahora queremos que el nuevo elemento (el 2) se agregue al final de lalista Añadir elementos por la cola • De forma mas general, si la lista tiene muchos elementos, hay que: 1. buscar el último elemento, es decir, recorrer la lista hasta encontrar el puntero cuyo siguiente es null. Guardar el puntero en la variable aux. 2. Reservar memoria para el nuevo elemento, guardar su puntero en nuevo. 3. Hacer que el campo siguiente del último elemento encontrado en ( 1) apunte el nuevo elemento: aux>sig=nuevo 4. Actualizar los campos de nuevo, con indicación de fin de lista. Añadir elementos por la cola Una aplicación: Matrices Dispersas • En lugar de almacenar un float (32 o 64 bits) por elemento, se busca una representación que ahorre memoria: Matriz Dispersa • Lista de Filas donde cada fila es una lista de valores no nulos: – El nodo fila contiene número de fila, puntero a la siguiente fila y puntero a la lista de elementos no nulos – El nodo elemento contiene el float, la columna en la que está y un puntero al siguiente elemento. Matriz Dispersa • Hacer el cálculo para el ejemplo que mostramos usando elementos de tipo float de 32 bits, del ahorro de espacio conseguido usando listas enlazadas. Ejercicio Matriz Dispersa • Hallar la suma de los elementos de dos matrices dispersas representada con listas enlazadas en C. • Hallar la multiplicación de dos matrices representadas con listas enlazadas • Efectuar las mismas operaciones, suma y multiplicación representando las matrices mediante vectores de dos dimensiones estáticos. • Comparar, usando gprof, el rendimiento de ambas implementaciones. • Comparar, para los mismos datos, el espacio ocupado en ambas representaciones.