0% encontró este documento útil (0 votos)
10 vistas25 páginas

14

El documento aborda el tema de listas enlazadas en programación, comparando estructuras estáticas y dinámicas. Se explican conceptos clave como la creación de nodos, punteros de entrada, y diversas operaciones que se pueden realizar con listas enlazadas, incluyendo inserciones y eliminaciones. Además, se clasifica las listas enlazadas en varias categorías y se proporciona ejemplos de algoritmos para su implementación en C.

Cargado por

javiherr11
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
0% encontró este documento útil (0 votos)
10 vistas25 páginas

14

El documento aborda el tema de listas enlazadas en programación, comparando estructuras estáticas y dinámicas. Se explican conceptos clave como la creación de nodos, punteros de entrada, y diversas operaciones que se pueden realizar con listas enlazadas, incluyendo inserciones y eliminaciones. Además, se clasifica las listas enlazadas en varias categorías y se proporciona ejemplos de algoritmos para su implementación en C.

Cargado por

javiherr11
Derechos de autor
© © All Rights Reserved
Nos tomamos en serio los derechos de los contenidos. Si sospechas que se trata de tu contenido, reclámalo aquí.
Formatos disponibles
Descarga como PDF, TXT o lee en línea desde Scribd
Está en la página 1/ 25

Programación II

Listas enlazadas -1-

LISTAS ENLAZADAS
Estructuras estáticas frente a dinámicas.................................................................................................................1
Listas enlazadas........................................................................................................................................................3
Clasificación de las listas enlazadas.................................................................................................................... 4
Declaración y creación de un nodo......................................................................................................................... 4
Puntero de entrada a la lista.................................................................................................................................... 6
Operaciones con listas enlazadas............................................................................................................................ 7
Creación de una lista enlazada............................................................................................................................. 8
Recorrido de una lista........................................................................................................................................... 9
Insertar un nodo como primero de la lista......................................................................................................... 10
Insertar un nodo como último de la lista............................................................................................................ 10
Insertar un nodo en su posición en una lista ordenada ..................................................................................... 11
Eliminar primer nodo de la lista......................................................................................................................... 12
Eliminar último nodo de la lista......................................................................................................................... 12
Eliminar un nodo intermedio de la lista............................................................................................................. 13
Eliminar todos los nodos de una lista................................................................................................................. 13
Ejercicios resueltos................................................................................................................................................ 14
Ejercicios propuestos............................................................................................................................................. 21

Estructuras estáticas frente a dinámicas


Muchos problemas de cálculo implican la utilización de listas de elementos. La estructura que
hasta ahora hemos utilizado para implementar una lista es el array, la cual es una estructura
estática. Una estructura estática es aquella cuyo tamaño queda fijado en tiempo de
compilación, y por tanto permanece inalterable en memoria mientras se esté ejecutando el
programa que la contiene.

Trabajando con listas, muchas veces no sabremos en tiempo de desarrollo/compilación, el


número de componentes que ésta tendrá. Un método usual para resolver esta situación es
declarar un array lo suficientemente grande para almacenar la máxima cantidad de datos que
cabe esperar en cualquier ejecución del programa (MAXDIM: dimensión física o máxima del
array).

Puesto que normalmente tendremos menos datos que dicha dimensión máxima, en los
programas se maneja en una variable la longitud del "subarray" en el que hemos colocado los
valores (diml: dimensión lógica o efectiva) y únicamente a esa parte del array es a la que se
accede. Esta dimensión lógica puede variar durante la ejecución del programa, y por supuesto
en distintas ejecuciones del mismo (desde 1 a la dimensión máxima del array), pero sin
embargo la propia dimensión máxima del array no puede variar a no ser que volvamos a
compilar el programa.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -2-

Figura 1. Array. Estructura estática con dimensión máxima y dimensión efectiva

Hay otra técnica para representar una lista: las listas enlazadas. En esta técnica los elementos
de la lista (también llamados NODOS), son variables dinámicas, que se crean durante la
ejecución del propio programa sólo cuando de necesiten, y se destruirán igualmente cuando
ya no se necesiten. Estos nodos, en vez de ir “físicamente” uno detrás de otro como en un
array, van “lógicamente” uno detrás de otro. Cada elemento contiene, además de la
información propia que se desea guardar en cada uno de ellos (como en un elemento de un
array), información sobre la posición del siguiente nodo. ¿Cómo?. Almacenándose en cada
nodo un puntero al siguiente nodo de la lista enlazada.

No es necesario saber de antemano la dimensión de la lista (no es necesario que definamos


una dimensión máxima), puesto que tal lista puede expandirse o reducirse conforme se
ejecute el programa, creándose o destruyéndose los nodos necesarios, por ser variables
dinámicas. La única limitación es la cantidad de espacio de memoria disponible en el
segmento montículo. Las estructuras de datos que se construyen usando esta técnica se llaman
estructuras de datos dinámicas.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -3-

Una estructura de datos dinámica de construye con nodos. Cada nodo está formado de

 Componente: el dato a almacenar en cada posición o nodo de la lista.


 Puntero: el enlace al siguiente nodo de la lista.

Figura 2. Lista enlazada. Estructura dinámica compuesta por nodos

Listas enlazadas
Se llaman así ya que cada nodo contiene un puntero que lo enlaza con el siguiente nodo. Las
lista enlazadas son estructura de datos dinámicas, que se van construyendo dentro de la
ejecución del programa. El acceso a una lista enlazada es como el juego de los niños “la caza
del tesoro”, en el que a cada niño se le da una pista del lugar oculto de la siguiente pista y la
cadena de pistas conduce finalmente al tesoro.

Accederemos a la lista enlazada recordando (guardando) en un puntero la dirección del


primer nodo de la lista. Este puntero se llama puntero de entrada a la lista, y como hemos
dicho apunta al primer nodo. Cualquier otro nodo es accedido mediante el campo puntero del
nodo que le precede.

Para crear una lista enlazada, comenzamos creando el primer nodo1 y guardando su dirección
en el puntero de entrada a la lista. Crearemos entonces un segundo nodo y almacenamos su
dirección en el campo de enlace del primer nodo. Continuamos este proceso, creando un

1
Recordar que los nodos son variables dinámicas que se crearán con la función que convenga: calloc ó malloc

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -4-

nuevo nodo y almacenando su dirección en el campo enlace del nodo anterior, hasta que
alcanzamos el final de la lista.

En el puntero de enlace del último nodo de la lista almacenaremos la constante NULL, para
marcar que ese nodo no tiene “siguiente”.

Clasificación de las listas enlazadas


Las listas enlazadas se pueden clasificar en 4 categorías:
 Lista simplemente enlazada. Cada nodo contiene un único enlace que le conecta con el
nodo siguiente o sucesor.
 Lista doblemente enlazada. Cada nodo contiene dos enlaces, uno a su nodo predecesor y
otro a su nodo sucesor.
 Lista circular simplemente enlazada. Es una lista simplemente enlazada en la que el
último nodo se enlaza con el primero.
 Lista circular doblemente enlazada. Es una lista doblemente enlazada en la que el
último y el primer nodo están doblemente enlazados entre sí.

En este tema se estudiarán sólo listas simplemente enlazadas.

Declaración y creación de un nodo


Un NODO en C puede declararse como un nuevo tipo de dato struct, de la siguiente forma:
typedef struct Nodo {
tipo_componente dato;
struct Nodo *sig;
} NODO;

Se ha declarado el tipo NODO con un componente genérico, para poder extender los
algoritmos que veremos a continuación. En cada implementación concreta tipo_componente
será un tipo de dato válido en C. Por ejemplo para crear nodos que almacenen un dato de tipo
long, podrá sustituirse el literal tipo_componente por el tipo de dato long o bien anteponer la
siguiente definición a la definición del tipo NODO:
typedef tipo_componente long;

Los nodos pueden tener varios componentes de datos, definiendo varios miembros en la
estructura. Por ejemplo la siguiente definición de NODO contienen 4 componentes de datos:
typedef struct Nodo_pers {

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -5-

char[80] nombre;
long num_matricula;
int edad;
float peso;
struct Nodo_pers *sig;
} NODO;

En los algoritmos que se desarrollarán a continuación simplificaremos la definición de los


nodos con un solo componente, que llamaremos dato, de tipo genérico tipo_componente.

Siempre la definición del tipo NODO debe de incluir un último miembro de enlace a un nodo
del mismo tipo, por tanto definido como puntero a la propia estructura definida para el nodo.
En el último ejemplo es el puntero sig a struct Nodo_pers.

Para crear un nodo puede utilizarse cualquiera de las funciones de reserva de memoria
dinámica. Siempre deberemos disponer de un puntero al tipo NODO con el que “sustentar” el
nodo.
En este ejemplo ese puntero es nuevo:

NODO *nuevo;
...
nuevo = (NODO *) malloc (sizeof (NODO));
/* Se carga el dato y el puntero del nuevo NODO
con los valores que corresponda */
nuevo -> dato = ...
nuevo -> sig = ...

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -6-

Puntero de entrada a la lista


Toda lista enlazada se sustenta simplemente mediante un puntero al primer nodo de la misma,
llamado puntero de entrada o puntero cabecera de la lista.

Este puntero de entrada deberá ser declarado como una variable puntero al tipo nodo de la
lista:
NODO *lista;

Figura 3. Puntero de entrada a la lista enlazada

Si la lista estuviera vacía, este puntero cabecera tendrá valor NULL, como por ejemplo, al
principio del programa, cuando todavía no se ha creado ningún nodo de la lista

NODO *lista = NULL;

Figura 4. Puntero de entrada a una lista vacía

Para pasar una lista a una función bastará pasar el puntero de entrada a la misma. Según la
necesidad de que la función modifique o no el contenido del puntero de entrada a la lista,
éste se pasará por valor o por referencia. Por referencia se deberá pasar un puntero a
puntero.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -7-

Operaciones con listas enlazadas


Seguidamente se muestran los algoritmos correspondientes a las principales operaciones que
pueden realizarse sobre listas enlazadas.
 Crear una lista enlazada
 Recorrer y visualizar una lista enlazada
 Insertar un nodo al principio de la lista
 Insertar un nodo al final de la lista
 Insertar un nodo en su posición, en una lista ordenada
 Eliminar el primer nodo de la lista
 Eliminar el último nodo de la lista
 Eliminar un nodo intermedio de la lista
 Eliminar una lista enlazada (todos los nodos de una lista)

Se presentan a continuación todos estos algoritmos. En los mismos se tendrá en cuenta la


siguiente nomenclatura:

− Definición de la estructura de los nodos


typedef struct Nodo {
tipo_componente dato;
struct Nodo *sig;
} NODO;

− Puntero de entrada a la lista


NODO *lista;

− Punteros auxiliares para el tratamiento en los algoritmos


NODO *nuevo;
NODO *indice;
NODO *anterior;

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -8-

Creación de una lista enlazada


Un algoritmo válido para la creación de una lista enlazada en memoria puede ser el siguiente.
lista = NULL
indice = NULL
Mientras queden elementos a añadir a la lista hacer
leer (info) /* Información a añadir como dato en el nodo */
crear un NODO apuntado por el puntero nuevo
nuevo -> dato = info
nuevo -> sig = NULL
Si (lista == NULL)
/* Es el primer nodo de la lista */
lista = nuevo
indice = nuevo
sino
/* No es el primer nodo de la lista */
/* Se incluye al final de la lista */
indice -> sig = nuevo
indide = nuevo
Fin Si
Fin Mientras

Para crear el NODO utilizaremos en C la función calloc ó malloc.

Figura 5. Creación del primer nodo de la lista

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas -9-

Figura 6. Creación de un nodo al final de la lista

Recorrido de una lista


Un algoritmo válido para el recorrido de una lista enlazada desde el primero hasta el último
nodo, mostrando el valor del dato de cada uno de sus nodos, puede ser el siguiente.
indice = lista
Mientras (indice != NULL) hacer
escribir (indice -> dato) /* Presentamos en valor del nodo */
indice = indice -> sig /* Apuntamos al siguiente */
Fin Mientras

Este algoritmo es válido incluso para listas vacías. En ese caso simplemente se sale del bucle
sin hacer nada.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 10 -

Insertar un nodo como primero de la lista


Un algoritmo válido para la inserción de un nodo al principio de una lista enlazada (como
primer nodo), puede ser el siguiente.
crear un NODO apuntado por el puntero nuevo
nuevo -> dato = info /* info es la información a añadir
como dato en el nodo */

nuevo -> sig = lista


lista = nuevo

Este algoritmo es válido incluso para listas vacías. En ese caso el puntero lista estará a NULL,
que será el valor que se cargue en el puntero sig del nodo creado.

Insertar un nodo como último de la lista


Un algoritmo válido para la inserción de un nodo al final de una lista enlazada (como último
nodo), puede ser el siguiente.
crear un NODO apuntado por el puntero nuevo
nuevo -> dato = info /* info es la información a añadir
como dato en el nodo */
nuevo -> sig = NULL /* Como será el último, su puntero sig a NULL */

indice = lista
Si (indice == NULL)
/* Lista vacía. El nodo es el primero */
lista = nuevo
sino
/* Recorremos la lista hasta llegar a su final */
Mientras (indice -> sig != NULL) hacer
indice = indice -> sig
Fin Mientras

/* Apuntamos al nuevo nodo desde el último de la lista actual */


indice -> sig = nuevo

Fin Si

Este algoritmo es válido incluso para listas vacías, en cuyo caso el nodo a añadir será el
primero.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 11 -

Insertar un nodo en su posición en una lista ordenada


Un algoritmo válido para la inserción de un nodo dentro de una lista ordenada de forma
ascendente respecto al contenido de dato, en la posición que le corresponda, puede ser el
siguiente.
crear un NODO apuntado por el puntero nuevo
nuevo -> dato = info /* info es la información a añadir
como dato en el nodo */
nuevo -> sig = NULL

indice = lista
anterior = NULL
Si (indice == NULL)
/* Lista vacía. El nodo es el primero */
lista = nuevo
sino
/* Recorremos la lista hasta encontrar un nodo con el contenido
de dato mayor que el del nodo a insertar, o bien hasta llegar
al final de la lista */
Mientras (indice -> dato < nuevo -> dato)
AND (indice -> sig != NULL) hacer
anterior = indice
indice = indice -> sig
Fin Mientras

Si (indice -> sig == NULL) AND (indice -> dato < nuevo -> dato)
/* El nodo se inserta al final de la lista */
nuevo -> sig = NULL
indice -> sig = nuevo
sino
Si (anterior == NULL)
/* El nodo se inserta como primero */
nuevo -> sig = lista
lista = nuevo
sino
/* El nodo se inserta en medio de la lista */
nuevo -> sig = indice
anterior -> sig = nuevo
Fin Si
Fin Si
Fin Si

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 12 -

Eliminar primer nodo de la lista


Un algoritmo válido para eliminar el primer nodo de una lista enlazada, puede ser el siguiente.
Si (lista != NULL)
indice = lista
lista = indice -> sig
liberar memoria del NODO apuntado por el puntero indice
Fin Si

El algoritmo, lo primero que comprobamos es que la lista no esté vacía. De ser así, no se hace
nada. Si la lista no tuviera más que un nodo, se eliminaría dicho nodo y el puntero lista
quedaría a valor NULL (valor del puntero sig del primer nodo), es decir lista vacía.

Para liberar la memoria del nodo que eliminamos de la lista utilizaremos en C la función
free.

Eliminar último nodo de la lista


Un algoritmo válido para eliminar el último nodo de una lista enlazada, puede ser el siguiente.
Si (lista != NULL)
indice = lista
anterior = NULL

/* Recorremos la lista para localizar el último nodo */


Mientras (indice -> sig != NULL) hacer
anterior = indice
indice = indice -> sig
Fin Mientras

Si (anterior == NULL)
/* Sólo existe un nodo. Eliminamos primer nodo */
lista = NULL
liberar memoria del NODO apuntado por el puntero indice
sino
anterior -> sig = NULL
liberar memoria del NODO apuntado por el puntero indice
Fin Si
Fin Si

El algoritmo, lo primero que comprueba es que la lista no esté vacía. De ser así, no se hace
nada. Este algoritmo es válido incluso para listas con un único nodo. En ese caso libera el
primer y único nodo de la lista, quedando la misma vacía (puntero lista a valor NULL).

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 13 -

Eliminar un nodo intermedio de la lista


Un algoritmo válido para eliminar un nodo intermedio de una lista enlazada, puede ser el
siguiente.
Si (lista != NULL)
indice = lista
anterior = NULL

/* Recorremos la lista para localizar el nodo buscado */


Mientras (indice -> dato != datobuscado)
AND (indice -> sig != NULL) hacer
anterior = indice
indice = indice -> sig
Fin Mientras

Si (indice -> dato == datobuscado)


Si (anterior == NULL)
/* Eliminamos primer nodo */
lista = indice -> sig
liberar memoria del NODO apuntado por el puntero indice
sino
anterior -> sig = indice -> sig
liberar memoria del NODO apuntado por el puntero indice
Fin Si
Fin Si
Fin Si

El algoritmo, lo primero que comprueba es que la lista no esté vacía. De ser así, no se hace
nada. Este algoritmo es válido incluso para listas con un único nodo. En ese caso libera el
primer y único nodo de la lista, quedando la misma vacía (puntero lista a valor NULL).

Eliminar todos los nodos de una lista


Un algoritmo válido para eliminar todos los nodos de una lista enlazada, puede ser el
siguiente.
indice = lista
Mientras (lista != NULL) hacer
lista = lista -> sig
liberar memoria del NODO apuntado por el puntero indice
indice = lista
Fin Mientras

Este algoritmo es válido incluso para listas vacías. En ese caso no hace nada.
Al finalizar el algoritmo la lista queda vacía, es decir el puntero lista a valor NULL y liberada
la memoria de todos los nodos.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 14 -

Ejercicios resueltos

EJERCICIO 1
Escribir una función que devuelva “cierto” si una lista que se la pasa como parámetro está
vacía, y “falso” en otro caso.

Codificación
Suponiendo las siguientes declaraciones:
typedef int Item;
typedef struct Nodo {
Item dato;
struct Nodo *sig;
} NODO;

Una codificación de la función EstaVacia puede ser:


int EstaVacia (NODO *lst) {
return (lst == NULL)
}

Comentario
Suponiendo que en el módulo llamador (función main, por ejemplo) el puntero de entrada a
la lista es
NODO *lista;
Un ejemplo de llamada a esta función será
if (EstaVacia (lista))
.....
else
.....

En este caso la función EstaVacia recibe en su parámetro formal lst (definido como
NODO *) el valor del parámetro real en la llamada lista (puntero de entrada a la lista).
Dentro de la función tenemos acceso a la lista a través del puntero lst, pero no podemos
cambiar su primer nodo por otro, pues no podemos modificar dentro de la función el
contenido del puntero lista, que es el parámetro real en la llamada.

Todo esto se representa en la siguiente figura.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 15 -

Figura 7. Paso de una lista a una función. Paso por valor de su puntero de entrada

En la figura se representa:
A) Situación en el módulo llamador, antes de llamar a la función. La lista es sustentada por el
puntero lista de entrada a la misma.
B) Situación vista “desde dentro” de la función llamada, cuando ésta se está ejecutando.
Tenemos acceso a la lista porque en el puntero lst se ha recibido el valor parámetro real en
la llamada lista, pero no tenemos acceso al propio parámetro real lista, por lo que no
podremos modificar su contenido. Si modificamos dentro de la función la dirección del
primer nodo al que apunta, esto no tendrá efecto en lista al terminar la función.
Dentro de la función lst será un puntero que contendrá la dirección del primer nodo

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 16 -

EJERCICIO 2
Escribir una función que devuelva el número de nodos de una lista enlazada.
Codificación
Suponiendo las declaraciones del ejercicio anterior, la función NumeroDeNodos puede ser:
int NumeroDeNodos (NODO *lst) {
int k=0;
NODO *p;
p = lst;
while (p != NULL) {
k++;
p = p -> sig;
}
return (k);
}

EJERCICIO 3
Escribir una función que elimine el nodo i de una lista enlazada.

Análisis
Deberemos recorrer la lista contando el número de nodos, terminando cuando encontremos el
nodo i a eliminar. Se hace un tratamiento diferente si debe eliminarse el primer nodo u otro de
la lista.
Si la lista tuviera menos de i nodos, o el valor de i recibido fuera cero o negativo, la función
terminará sin hacer nada.

Codificación
Suponiendo las declaraciones del ejercicio anterior, la función EliminaPosicion puede ser:
void EliminaPosicion (NODO **lst, int i) {
int k;
NODO *indice, *anterior;

if (i <= 0) return;

indice = *lst; /* indice apunta al primer nodo de la lista */


k = 1;
anterior = NULL;

while ((k<i) && (indice != NULL)) {


k++;
anterior = indice;
indice = indice -> sig;
}

if (k==i)
{ if (anterior == NULL)

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 17 -

*lst = indice -> sig;


else
anterior -> sig = indice -> sig;

free (indice);
}
}

Comentario
Suponiendo que en el módulo llamador (función main, por ejemplo) el puntero de entrada a
la lista es
NODO *lista;
Un ejemplo de llamada a esta función será
EliminaPosicion (&lista, 5)

En este caso la función EliminaPosicion recibe en su parámetro formal lst (definido como
NODO **) la dirección del parámetro real en la llamada lista (puntero de entrada a la lista).
Dentro de la función tenemos acceso al propio parámetro real lista (a través de *lst), por lo
que podemos modificar dentro de la función el contenido del puntero lista (podemos
cambiar su primer nodo por otro).

Todo esto se representa en la siguiente figura.

Figura 8. Paso de una lista a una función. Paso por referencia de su puntero de entrada

En la figura se representa:

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 18 -

A) Situación en el módulo llamador, antes de llamar a la función. La lista es sustentada por el


puntero lista de entrada a la misma.
B) Situación vista “desde dentro” de la función llamada, cuando ésta se está ejecutando. En el
puntero lst se ha recibido la dirección del parámetro real en la llamada lista. Tenemos
acceso al propio parámetro real lista (dentro de la función *lst representa a lista), por lo
que podremos modificar su contenido. Es decir podemos cambiar su primer nodo por otro,
y esto tendrá efecto en lista al terminar la función.
Dentro de la función lst será un puntero que contendrá la dirección de lista, por lo que *lst
será lista.

En el caso de funciones que pueden necesitar cambiar el primero nodo de una lista por otro,
la forma de pasar la lista a la función deber ser a través de un puntero a puntero (NODO
**).

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 19 -

EJERCICIO 4
Escribir una función que reciba como parámetro una lista enlazada y un valor del tipo “dato”
de los nodos de la lista. Deberá crear un nuevo nodo e insertarlo como primero de la lista,
almacenando en el mismo el valor del tipo “dato” recibido.

Codificación
Suponiendo las declaraciones del ejercicio anterior, la función InsertaPrimero puede ser:
void InsertaPrimero (NODO **lst, Item info) {
NODO *nuevo;

nuevo = (NODO *) malloc (sizeof(NODO));


nuevo -> dato = info;
nuevo -> sig = *lst;

*lst = nuevo;
}

EJERCICIO 5
Escribir una función que reciba como parámetro una lista enlazada y un valor a buscar en los
nodos de la lista. Nos devolverá como valor de retorno de la función un puntero al nodo que
contenga la primera aparición del valor a buscar, y en un parámetro entero el número de dicho
nodo. En caso de no encontrar el valor buscado el puntero lo devolverá con valor NULL y el
entero con valor 0.

Codificación
Suponiendo las declaraciones del ejercicio anterior, la función BuscarLista puede ser:
NODO *BuscarLista (NODO *lst, Item info, int *num) {
NODO *indice;

for (*num=1, indice=lst; indice!=NULL; indice = indice -> sig, *num++)


if (indice -> dato == info)
return (indice);

*num = 0;
return (NULL);
}

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 20 -

EJERCICIO 6
Escribir un programa que genere una lista enlazada de números enteros aleatorios de tal forma
que se almacenen en la lista en el orden en que se generan. Posteriormente deberá indicar el
número de nodos de la lista y presentarse la lista completa en pantalla. Antes de finalizar el
programa deberá eliminarse la lista enlazada.

Programa codificado en C
Ver fuente LISTRAND.C

EJERCICIO 7
Un conjunto es una secuencia de elementos del mismo tipo, sin duplicados.
Escribir un programa para representar conjuntos de números enteros mediante una lista
enlazada. El programa generará un conjunto de números enteros aleatorios. La dimensión del
conjunto será también un valor aleatorio entre 0 y 50.

El conjunto debe contemplar las siguientes operaciones:


 PerteneceConjunto, para indicar si un elemento se encuentra en el conjunto
 EsVacioConjunto, para indicar si el conjunto está vacío.
 CardinalConjunto, para indicar cuantos elementos tiene el conjunto
 AnadeElementoConjunto, para añadir un elemento al conjunto, como primer elemento,
controlando que el elemento no se encuentre ya en el conjunto.
 BorraElementoConjunto, para eliminar un elemento del conjunto.
 VacíaConjunto, para eliminar todo el conjunto, convirtiéndolo en un conjunto vacío.
 ListaConjunto, para escribir en pantalla todos los elementos del conjunto.

Programa codificado en C
Ver fuente CONJUNTO.C

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 21 -

Ejercicios propuestos

Comentarios para todos los programas propuestos:


 Los programas deberá realizarse de forma que se apoyen en el uso de funciones que
realicen las tareas elementales de tratamiento de la lista.
 Estas funciones, y los propios programas, deberán funcionar correctamente incluso para
valores límite como por ejemplo listas vacías.
 Antes de finalizar los programas, deberá eliminarse la lista enlazada.

EJERCICIO 8
Escribir un programa que genere una lista enlazada de números enteros positivos y aleatorios,
de tal forma que se almacenen en la lista en el orden en que se generan. La lista podrá
contener elementos repetidos.
Posteriormente entrará en un bucle de forma que solicitará por pantalla un número y lo
localizará en la lista, eliminando todos los nodos de la lista que contengan dicho valor,
solicitando posteriormente otro número y actuando de la misma forma.
Deberá siempre presentar el número de nodos al comienzo y al final de cada iteración del
bucle, de forma que comprobemos cuantos nodos se eliminan en cada momento.
El bucle terminará cuando se teclee un número negativo.

EJERCICIO 9
Escribir un programa que genere una lista enlazada de números enteros y aleatorios, de tal
forma que se almacenen en la lista de forma ordenada. La lista podrá contener elementos
repetidos.

Posteriormente deberá indicar el número de nodos de la lista y presentarse la lista completa en


pantalla.

Más tarde solicitará un número entero por teclado y eliminará todos los nodos de la lista que
cumplan la condición de que su contenido es estrictamente mayor que el valor tecleado.

Por último se indicará el número de nodos de la lista resultante y se presentará completa en


pantalla.

EJERCICIO 10

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 22 -

Escribir un programa que genere una lista enlazada de números enteros positivos y aleatorios,
de tal forma que se almacenen en la lista en el orden en que se generan. La lista podrá
contener elementos repetidos.

Posteriormente deberá indicar el número de nodos de la lista y presentarse la lista completa en


pantalla.

Más tarde generará una segunda lista en la que se almacenarán los nodos de la primera pero
ordenados descendentemente, y ya sin elementos repetidos.

Por último se indicará el número de nodos de esta segunda lista y se presentará completa en
pantalla.

EJERCICIO 11
Con la representación de conjuntos realizada en un ejercicio anterior, añadir las siguientes
operaciones básicas:
 UnionConjuntos, para realizar la unión del conjunto c1 con el c2 en el conjunto c3. Por
tanto c3 contendrá todos los elementos de c1 y c2 no repetidos.
 DiferenciaConjuntos:, para realizar la diferencia del conjunto c1 con el c2 dejando el
resultado en c3. Por tanto c3 contendrá todos los elementos de c1 que no estén en c2.
 IncluidoEnConjunto, para indicar si c1 está incluido en c2. Para que esto ocurra todos
los elementos de c1 deben estar en c2.
 InterseccionConjuntos, para realizar en c3 la intersección de los conjuntos c1 y c2. Por
tanto c3 contendrá todos los elementos de c1 que también están en c2.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 23 -

EJERCICIO 12
Supongamos un fichero que tiene en cada línea un nombre de persona, y que nos piden
presentarlos ordenados alfabéticamente en pantalla.

Solución 1:
Crear un array de cadenas de caracteres en memoria, cargar el fichero en dicho array, ordenar
el array y presentarlo en pantalla.

Recordemos que el array es una estructura estática cuyo tamaño queda fijado en tiempo de
compilación, y por lo tanto permanece inalterable en memoria mientras se está ejecutando el
programa.

Como normalmente el número de elementos a utilizar variará en cada ejecución (el fichero de
una ejecución a otra puede tener distinto número de elementos), estaremos obligados a
trabajar con una dimensión física del array (MAXDIM, el máximo número de elementos que
se prevé tratar en cualquier ejecución del programa) que se fijará en tiempo de compilación, y
otra efectiva o lógica, de forma que a través de una variable manejemos la longitud del
subarray en la que hemos colocado valores en esa ejecución, y únicamente a esa parte del
array es a la que accedamos y tratemos.
Esta dimensión efectiva puede variar en distintas ejecuciones del programa, pero sin embargo
la dimensión máxima del array no es posible modificarla, a no ser que modifiquemos el fuente
y volvamos a compilar el programa.

Problemas:
 En tiempo de programación debemos plantearnos y escoger la dimensión física del array.
Cualquier futura modificación de ella requiere la intervención del programador, y volver a
compilar el programa.
 Siempre existirá ese fatal día en que tengamos que tratar más elementos que los máximos
esperados.
 El array no puede definirse todo lo grande que se desee, pues estamos limitados por el
tamaño del segmento de datos.

Solución 2:
Utilizar una lista enlazada que se irá creando en tiempo de ejecución y así siempre se
acomodará al número de elementos a tratar, ni uno más ni uno menos.
Se leerá el fichero de entrada y por cada registro leído se creará un nodo en la lista de forma
ordenada. Posteriormente se presenta la lista en pantalla.

No es necesario saber de antemano cómo será la lista de larga (no es necesario que definamos
una dimensión máxima), puesto que tal lista puede expandirse conforme se ejecute el
programa, creándose los nodos necesarios, por ser variables dinámicas.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 24 -

Problemas:
 Dificultad de tratamiento.

Ventajas:
 El tamaño de la lista se acomoda exactamente al número de datos a almacenar en cada
ejecución. No es necesario que en tiempo de programación debemos plantearnos la
dimensión física a dar a la lista.
 Los nodos de la lista enlazada se crean en el montículo, y éste es mucho mayor que el
segmento de datos, por lo que las listas enlazadas podrán ser mucho más grandes que las
listas estáticas o arrays.

Realizar un programa que utilice la solución 2 para, a partir de un fichero de texto que
contiene varios registros con una cadena de caracteres en cada registro, generar un segundo
fichero en disco ordenado.

EJERCICIO 13
Considérense la siguiente estructura
typedef struct Nodo {
int PR_id;
long PR_time;
float PR_pc;
struct Nodo *sig;
} PROCESO;

que sirven como base para la construcción de una lista enlazada de nodos PROCESO.

Construir las siguientes funciones para el manejo de la "lista enlazada de procesos".

int SinProcesos (PROCESO *lst)


Devolverá “cierto” si no hay procesos en la lista (está vacía) que recibe como parámetro, y
“falso” en caso contrario.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)
Programación II
Listas enlazadas - 25 -

void InsertarPrimero (PROCESO **lst, PROCESO proc);


Insertará el proceso recibido proc como primer proceso de la lista que recibe como parámetro.

void InsertarUltimo (PROCESO **lst, PROCESO proc);


Insertará el proceso recibido proc como último proceso de la lista que recibe como parámetro.

void EliminarPrimero (PROCESO **lst);


Eliminará el primer proceso de la lista que recibe como parámetro.

void EliminarUltimo (PROCESO **lst);


Eliminará el último proceso de la lista que recibe como parámetro.

void EliminarPorId (PROCESO **lst, int id_proceso);


Eliminará de la lista que recibe como parámetro, el proceso que tenga en su campo PR_id el
valor recibido en id_proceso. Dentro de la lista no pueden existir dos procesos con el mismo
PR_id. Si no existiera ningún proceso con el valor de PR_id, no se realizará ninguna acción
sobre la lista.

void EliminarPorPc (PROCESO **lst, float pc_proceso);


Eliminará de la lista que recibe como parámetro, todos los procesos que tengan en su campo
PR_pc el valor recibido en pc_proceso. Dentro de la lista pueden existir entre 0 y n procesos
con el mismo PR_pc. Si no existiera ninguno, no se realizará ninguna acción sobre la lista.

int NumeroDeProcesos (PROCESO *lst);


Devolverá el número de procesos existentes en la lista que recibe como parámetro.

void EliminarListaProcesos (PROCESO **lst);


Eliminará de la lista que se recibe como parámetro, todos los procesos, dejando la lista vacía.

void SublistaProcesosTime (PROCESO **lst, PROCESO **lst_t,


long time_p);
Creará una sublista sustentada en lst_t, con todos los procesos de la lista que se recibe como
parámetro cuyo PR_time sea igual o superior al valor time_p recibido, pero sin eliminar los
procesos de la lista original.

Grado en Ingeniería Informática – Programación II


Departamento de Informática y Automática – Universidad de Salamanca (v 1112)

También podría gustarte