DEFINICIN La forma ms simple de estructura dinmica es la lista abierta. En esta forma los nodos se organizan de modo que cada uno apunta al siguiente, y el ltimo no apunta a nada, es decir, el puntero del nodo siguiente vale NULL. En las listas abiertas existe un nodo especial el primero. Normalmente diremos que nuestra lista es un puntero a ese primer nodo y llamaremos a ese nodo la cabeza de la lista. Eso es porque mediante ese nico puntero podemos acceder a toda la lista. !uando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista est vac"a. El nodo t"pico para construir listas tiene esta forma struct nodo # int dato$ struct nodo %siguiente$ &$ DECLARACIONES DE TIPOS PARA MANEJAR LISTAS EN C Normalmente se definen varios tipos que facilitan el mane'o de las listas, en !, la declaraci(n de tipos puede tener una forma parecida a esta typedef struct )nodo # int dato$ struct )nodo %siguiente$ & tipoNodo$
typedef tipoNodo %pNodo$ typedef tipoNodo %Lista$ tipoNodo es el tipo para declarar nodos, evidentemente. pNodo es el tipo para declarar punteros a un nodo. Lista es el tipo para declarar listas, como puede verse, un puntero a un nodo y una lista son la misma cosa. En realidad, cualquier puntero a un nodo es una lista, cuyo primer elemento es el nodo apuntado. Es muy importante que nuestro programa nunca pierda el valor del puntero al primer elemento, ya que si no existe ninguna copia de ese valor, y se pierde, ser imposible acceder al nodo y no podremos liberar el espacio de memoria que ocupa. * ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS OPERACIONES BSICAS CON LISTAS !on las listas tendremos un peque+o repertorio de operaciones bsicas que se pueden realizar ,+adir o insertar elementos. -uscar o localizar elementos. -orrar elementos. .overse a trav/s de una lista, anterior, siguiente, primero. !ada una de estas operaciones tendr varios casos especiales, por e'emplo, no ser lo mismo insertar un nodo en una lista vac"a, o al principio de una lista no vac"a, o la final, o en una posici(n intermedia. INSERTAR ELEMENTOS EN UNA LISTA ABIERTA INSERTAR UN ELEMENTO EN UNA LISTA VACA Este es, evidentemente, el caso ms sencillo. 0artiremos de que ya tenemos el nodo a insertar y, por supuesto un puntero que apunte a /l, adems el puntero a la lista valdr NULL El proceso es muy simple, bastar con que *. nodo12siguiente apunte a NULL. 3. Lista apunte a nodo. INSERTAR UN ELEMENTO EN LA PRIMERA POSICIN DE UNA LISTA 0odemos considerar el caso anterior como un caso particular de /ste, la nica diferencia es que en el caso anterior la lista es una lista vac"a, pero siempre podemos, y debemos considerar una lista vac"a como una lista. 4e nuevo partiremos de un nodo a insertar, con un puntero que apunte a /l, y de una lista, en este caso no vac"a El proceso sigue siendo muy sencillo *. 5acemos que nodo12siguiente apunte a Lista. 3. 5acemos que Lista apunte a nodo. 3 ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS INSERTAR UN ELEMENTO EN LA LTIMA POSICIN DE UNA LISTA Este es otro caso especial. 0ara este caso partiremos de una lista no vac"a El proceso en este caso tampoco es excesivamente complicado *. Necesitamos un puntero que se+ale al ltimo elemento de la lista. La manera de conseguirlo es empezar por el primero y avanzar 6asta que el nodo que tenga como siguiente el valor NULL. 3. 5acer que nodo12siguiente sea NULL. 7. 5acer que ultimo12siguiente sea nodo. INSERTAR UN ELEMENTO A CONTINUACIN DE UN NODO CUALQUIERA DE UNA LISTA 4e nuevo podemos considerar el caso anterior como un caso particular de este. ,6ora el nodo 8anterior8 ser aquel a continuaci(n del cual insertaremos el nuevo nodo 9uponemos que ya disponemos del nuevo nodo a insertar, apuntado por nodo, y un puntero al nodo a continuaci(n del que lo insertaremos. El proceso a seguir ser *. 5acer que nodo12siguiente se+ale a anterior12siguiente. 3. 5acer que anterior12siguiente se+ale a nodo. 7 ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS LOCALIZAR ELEMENTOS EN UNA LISTA ABIERTA .uy a menudo necesitaremos recorrer una lista, ya sea buscando un valor particular o un nodo concreto. Las listas abiertas s(lo pueden recorrerse en un sentido, ya que cada nodo apunta al siguiente, pero no se puede obtener, por e'emplo, un puntero al nodo anterior desde un nodo cualquiera si no se empieza desde el principio. 0ara recorrer una lista procederemos siempre del mismo modo, usaremos un puntero auxiliar como "ndice *. ,signamos al puntero "ndice el valor de Lista. 3. ,briremos un bucle que al menos debe tener una condici(n, que el "ndice no sea NULL. 7. 4entro del bucle asignaremos al "ndice el valor del nodo siguiente al "ndice actual. ELIMINAR ELEMENTOS EN UNA LISTA ABIERTA 4e nuevo podemos encontrarnos con varios casos, segn la posici(n del nodo a eliminar. ELIMINAR EL PRIMER NODO DE UNA LISTA ABIERTA Es el caso ms simple. 0artiremos de una lista con uno o ms nodos, y usaremos un puntero auxiliar, nodo *. 5acemos que nodo apunte al primer elemento de la lista, es decir a Lista. 3. ,signamos a Lista la direcci(n del segundo nodo de la lista Lista12siguiente. 7. Liberamos la memoria asignada al primer nodo, el que queremos eliminar. 9i no guardamos el puntero al primer nodo antes de actualizar Lista, despu/s nos resultar"a imposible liberar la memoria que ocupa. 9i liberamos la memoria antes de actualizar Lista, perderemos el puntero al segundo nodo. 9i la lista s(lo tiene un nodo, el proceso es tambi/n vlido, ya que el valor de Lista1 2siguiente es NULL, y despu/s de eliminar el primer nodo la lista quedar vac"a, y el valor de Lista ser NULL. 4e 6ec6o, el proceso que se suele usar para borrar listas completas es eliminar el primer nodo 6asta que la lista est/ vac"a. ELIMINAR UN NODO CUALQUIERA DE UNA LISTA ABIERTA : ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS En todos los dems casos, eliminar un nodo se puede 6acer siempre del mismo modo. 9upongamos que tenemos una lista con al menos dos elementos, y un puntero al nodo anterior al que queremos eliminar. ; un puntero auxiliar nodo. El proceso es parecido al del caso anterior *. 5acemos que nodo apunte al nodo que queremos borrar. 3. ,6ora, asignamos como nodo siguiente del nodo anterior, el siguiente al que queremos eliminar anterior12siguiente < nodo12siguiente. 7. Eliminamos la memoria asociada al nodo que queremos eliminar. 9i el nodo a eliminar es el ltimo, es procedimiento es igualmente vlido, ya que anterior pasar a ser el ltimo, y anterior12siguiente valdr NULL. EJERCICIO Prograa !"# "#$%ra "& #&' (ara )&gr#$ar #*##&%o$ a* )&)+)o, a* -)&a* . (or (o$)+)/& #& *a *)$%a #&*a0a1a2 =include>iostream.62 =include>stdio.62 struct nodo# int nro$ struct nodo %sgte$ &$ typedef struct nodo %?lista$ void insertainicio@?lista A, intB$ void insertafin@?lista A, intB$ void insertaenpos@?lista A, int,intB$ void imprimir@?listaB$ void main@B # ?lista lista<NULL$ int opc,valor, pos$ do# cout>>8*. Cnsertar al inicio8>>endl$ cout>>83. Cnsertar al final8>>endl$ cout>>87. Cnsertar en posicion8>>endl$ cout>>8:. Listado8>>endl$ cout>>8D. 9alir8>>endl$ cout>>8Cngrese una opcion8>>endl$ cin22opc$ D ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS sEitc6@opcB # case * cout>>8Falor a insertar al inicio8$ cin22valor$ insertainicio@lista,valorB$ breaG$ case 3 cout>>8Falor a insertar al final8$ cin22valor$ insertafin@lista,valorB$ breaG$ case 7 cout>>8Falor a insertar8$ cin22valor$ cout>>80osicion8$ cin22pos$ insertaenpos@lista,valor,posB$ breaG$ case : cout>>endl>>8listado8>>endl$ imprimir@listaB$ breaG$ & &E6ile@opcH<DB$ & void imprimir@?lista listaB # E6ile@lista H<NULLB #cout>>lista12nro>>endl$ lista<lista12sgte$ & cout>>endl$ & void insertainicio@?lista Alista,int valorB # ?lista q$ q<neE@struct nodoB$ q12nro<valor$ q12sgte<lista$ lista<q$ & void insertafin@?lista Alista,int valorB # ?lista t,q<neE@struct nodoB$ q12nro<valor$ q12sgte<NULL$ if@lista<<NULLB lista<q$ else # t<lista$ E6ile@t12sgteH<NULLBt<t12sgte$ t12sgte<q$ & & void insertaenpos@?lista Alista,int valor, int posB # ?lista q,t$ int i$ q<neE@struct nodoB$ I ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS q12nro<valor$ if@pos<<*B# q12sgte<lista$ lista<q$& else #t<lista$ for@i<*$tH<NULL$iJJB #if@i<pos1*B#q12sgte<t12sgte$ t12sgte<q$ return$ & t<t12sgte$ & & cout>>8posicion equivocada8>>endl$ & EJEMPLO 0rograma que ingrese elementos en una lista enlazada, elimina el primer elemento, elimina el elemento final y eliminar mediante un elemento dado. =include>iostream.62 =include>stdlib.62 =include>stdio.62 struct nodo# int nro$ struct nodo %sgte$ &$ typedef struct nodo %?lista$ void eliminainicio@?lista AB$ void eliminafin@?lista AB$ void eliminaelemento@?lista A, intB$ void eliminalista@?lista AB$ void insertalinicio@?lista A, intB$ void imprimir@?listaB$ void main@B # ?lista lista<NULL$ int opc,valor,n,i$ do# cout>>8*. Cnsertar elementos8>>endl$ cout>>83. Eliminar al inicio8>>endl$ cout>>87. Eliminar al final8>>endl$ cout>>8:. Eliminar elemento dado8>>endl$ cout>>8D. Eliminar toda la lista8>>endl$ cout>>8I. Listado8>>endl$ cout>>8K. 9alir8>>endl$ cout>>8Cngrese una opcion8>>endl$ cin22opc$ sEitc6@opcB # case * cout>>8Numero de elementos8$ cin22n$ for@i<L$i>n$iJJB #cout>>8Cngrese el elementos8$ cin22valor$ insertalinicio@lista,valorB$ K ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS & breaG$ case 3 cout>>8Elimina al inicio8$ eliminainicio@listaB$ breaG$ case 7 cout>>8Elimina al final8$ eliminafin@listaB$ breaG$ case : cout>>endl>>8elimina elemento8>>endl$ cout>>8Falor a eliminar8>>endl$cin22valor$ eliminaelemento@lista, valorB$ breaG$ case D cout>>endl>>8Elimina Lista8>>endl$ eliminalista@listaB$ breaG$ case I cout>>endl>>8Listado8>>endl$ imprimir@listaB$ breaG$ & &E6ile@opcH<KB$ & M%%%%%%%%%%%%%%%%%%Cmplementaci(n de funciones%%%%%%%%%%%%%%%%%%%%%M void imprimir@?lista listaB # E6ile@lista H<NULLB #cout>>lista12nro>>endl$ lista<lista12sgte$ & cout>>endl$ & void insertalinicio@?lista Alista,int valorB # ?lista q$ q<neE@struct nodoB$ q12nro<valor$ q12sgte<lista$ lista<q$ & void eliminainicio@?lista AlistaB # struct nodo %p$ if@listaH<NULLB # p<lista$ lista<lista12sgte$ delete@pB$ & & void eliminafin@?lista AlistaB # ?lista p,ant$ if@lista<<NULLB return$ p<lista$ N ESTRUCTURA DE DATOS AVANZADOS LISTAS ENLAZADAS if @lista12sgte<<NULLB lista<lista12sgte$ else # E6ile@p12sgteH<NULLB #ant<p$ p<p12sgte$ & ant12sgte<NULL$ & delete@pB$ & void eliminaelemento@?lista Alista, int valorB # ?lista p, ant$ p<lista$ E6ile@pH<NULLB # if@p12nro<<valorB #if@p<<listaB lista<lista12sgte$ else ant12sgte<p12sgte$ delete@pB$ return$ & ant<p$ p<p12sgte$ & & void eliminalista@?lista AlistaB # ?lista p$ E6ile@lista H<NULLB # p<lista$ lista<lista12sgte$ delete@pB$ & &