Você está na página 1de 8

03/05/13

Listas enlazadas en C

Listas enlazadas en C
Listas. Manejo del programa. Pilas y colas. Descarga de programas y datos.

Listas
Una lista es una estructura dinmica de datos. Cada objeto de la estructura est formado por los datos junto con un puntero al siguiente objeto. Al manejar punteros, los datos no tienen por qu estar situados en posiciones consecutivas de la memoria, y lo ms normal, es que estn dispersos. Debe imaginarse una lista de la siguiente forma:
( O ,O ,. . .,O ) 1 2 n

O1 es el primer objeto y est constituido por dos partes: los datos que pretendemos almacenar, que simblicamente llamaremos D1, y un puntero p1 que apuntar al siguiente objeto, en ste caso O2, es decir:

Discusin anloga para O2 y as sucesivamente. El final de la lista es el objeto On , cuyo puntero pn apunta a N U L L , es decir, a ningn sitio. De esta forma, podemos saber cual es el final de la lista. Cada elemento de datos, por ejemplo, el D1 de antes, ser una estructura (s t r u c t ) en el sentido del lenguaje C. Una lista vaca la representaremos de varias formas, que son: (smbolo matemtico del conjunto vaco), N U L Lo tambin por ( ) . Tcnicamente hablando, una lista lcontiene la direccin del primer objeto. Las listas no tienen problemas para crecer a izquierda, centro o derecha, dependiendo de lo que se pretenda conseguir. La nica pega es la memoria disponible. Tambin, las listas engloban a las pilas y colas. En consecuencia, saber manejar bien las listas, implica conocer ms cosas. Si, como consecuencia de la lectura de este artculo, llega a aprender y dominar las listas, y tiene tiempo, debe plantearse estudiar el lenguaje LISP (de LISt Processing, es decir, manejo de listas), que desde mi punto de vista, es el mejor lenguaje de programacin de todos los que conozco. Las listas tambin pueden estar doblemente enlazadas, es decir, cada objeto, contiene dos punteros, uno de ellos, al siguiente, como antes, y otro, al anterior. De esta forma, puede ir hacia adelante y hacia atrs (vea la siguiente figura):

Estas no las vamos a tratar aqu, aunque haciendo pequeas modificaciones al programa, lo conseguir sin dificultad.

Definicin de lista en C
Segn comentamos en el apartado anterior, es conveniente separar los datos de los punteros, as que la definicin de lista es la siguiente:
s t r u c tl i s t a{/ *l i s t as i m p l ee n l a z a d a* / s t r u c td a t od a t o s ; s t r u c tl i s t a* s i g ; } ;
personal.telefonica.terra.es/web/pegonrui/listas/listas.html 1/8

03/05/13

Listas enlazadas en C

donde en algn lugar hay que definir la estructura d a t o . Si cambiamos esta ltima, la lista tambin cambia y no hay que hacer cambios en ella. Las variables estn claras, d a t o ses el objeto D1 comentado antes, y s i ges el puntero que apunta al siguiente objeto (el p1 de la figura). Para inicializar una lista, basta con escribir:
s t r u c tl i s t a* l ;/ *d e c l a r a c i n* / l=N U L L ;/ *i n i c i a l i z a c i n* /

Esto par de sentencias constituyen la forma de crear una lista vaca, es decir, l = .

Operaciones con listas


Calcular la longitud de una lista
es decir, el nmero de elementos que contiene. El algoritmo no puede ser ms simple, inicializamos un contador a cero, y vamos recorriendo la lista, incrementando dicho contador, hasta encontrar el N U L Lfinal. En concreto:
/ *D e v u e l v el al o n g i t u dd eu n al i s t a* / i n tl o n g i t u d l ( s t r u c tl i s t a* l ){ s t r u c tl i s t a* p ; i n tn ; n=0 ; p=l ; w h i l e( p! =N U L L ){ + + n ; p=p > s i g ; } r e t u r nn ; }

Insertar un dato al comienzo de una lista


En concreto, sea xuna estructura tipo d a t oy l = ( O ,O ,. . .,O )una lista. Despus de la operacin debe quedar 1 2 n
l=( x ,O ,O ,. . .,O ) 1 2 n Para esto, debemos aprender a crear un nuevo nodo, lo cual es una llamada a m a l l o c , en concreto: s t r u c tl i s t a* c r e a n o d o ( v o i d ){ r e t u r n( s t r u c tl i s t a* )m a l l o c ( s i z e o f ( s t r u c tl i s t a ) ) ; }

Una vez visto esto, debemos hacer lo siguiente:

y la funcin es:
/ *I n s e r t ad a t oa lc o m i e n z od el al i s t a( p a r ap i l a s )* / s t r u c tl i s t a* i n s e r t a c o m i e n z o ( s t r u c tl i s t a* l ,s t r u c td a t ox ){ s t r u c tl i s t a* q ; q=c r e a n o d o ( ) ;/ *c r e au nn u e v on o d o* / q > d a t o s=x ;/ *c o p i a rl o sd a t o s* / q > s i g=l ; l=q ; r e t u r nl ; }

Insertar un dato al final de una lista


personal.telefonica.terra.es/web/pegonrui/listas/listas.html 2/8

03/05/13

Listas enlazadas en C

En concreto, sea xuna estructura tipo d a t oy l = ( O ,O ,. . .,O )una lista. Despus de la operacin debe quedar 1 2 n Aqu debemos distinguir si l = , o no. En el primer caso, debe quedar l = ( x ) , y si l debemos situarnos en el ltimo y asignar los punteros:
l=( O ,O ,. . .,O ,x ) 1 2 n

y la funcin es:
/ *I n s e r t ad a t oa lf i n a ld el al i s t a( p a r ac o l a s )* / s t r u c tl i s t a* i n s e r t a f i n a l ( s t r u c tl i s t a* l ,s t r u c td a t ox ){ s t r u c tl i s t a* p , * q ; q=c r e a n o d o ( ) ;/ *c r e au nn u e v on o d o* / q > d a t o s=x ;/ *c o p i a rl o sd a t o s* / q > s i g=N U L L ; i f( l= =N U L L ) r e t u r nq ; / *l al i s t aa r g u m e n t on oe sv a c a .S i t u a r s ee ne l l t i m o* / p=l ; w h i l e( p > s i g! =N U L L ) p=p > s i g ; p > s i g=q ; r e t u r nl ; }

Insertar un dato en una lista ordenada


Se entiende por lista ordenada una lista en la que se ha definido una funcin de ordenacin. Para aclarar las cosas, volvemos a nuestra imagen de lista:
l=( O ,O ,. . .,O ) 1 2 n Sabemos que cada objeto Oest formado por dos partes: el dato Dy el puntero s i g , con lo cual tenemos tambin la sucesin de los datos: ( D ,D ,. . .,D ) 1 2 n La lista est ordenada cuando tenemos definida una funcin binaria f sobre los datos de forma que (D , Eson estructuras tipo d a t o ):

D < E f(D,E) = -1 D = E f(D,E) = 0 D > E f(D,E) = 1 Como es evidente, los valores -1,0,1 son totalmente arbitrarios y podran sustituirse por cualquier otros. Lo hacemos as por analoga con los valores de retorno de algunas funciones del lenguaje C. Cuando se haya definido una funcin de ordenacin sobre una lista, diremos que la lista est ordenada, y escribiremos:
D 1 D 2 D n

o tambin:
O 1 O 2 O n

Veamos algunos ejemplos: En cada estructura D hay un campo para el nombre de la persona, de nombre n o m b r e . Si queremos ordenar la lista por orden alfabtico creciente de nombres de personas, la funcin de ordenacin es s t r c m pde la librera estndar, de forma que: D < E strcmp(D.nombre,E.nombre) = -1 D = E strcmp(D.nombre,E.nombre) = 0 D > E strcmp(D.nombre,E.nombre) = 1 Esta funcin distingue entre maysculas y minsculas, es decir, no es lo mismo Juan que juan, razn por la cual, la librera estndar provee tambin de la funcin s t r c a s e c m pque hace lo mismo, pero no distingue entre aquellas.
personal.telefonica.terra.es/web/pegonrui/listas/listas.html 3/8

03/05/13

Listas enlazadas en C

En cada estructura D hay un campo para la fecha de nacimiento de una persona, constituida por tres variables enteras, que son, el da, mes y ao de nacimiento, de nombres respectivos d , my a . Si queremos ordenar a las personas por fecha de nacimiento creciente, hemos de utilizar el orden lexicogrfico de estos tres valores, en concreto: 1. Comparamos en primer lugar los aos de nacimiento. Si D.a < E.a, hemos acabado, la fecha de D es inferior a la de E, retorna -1. Si D.a > E.a, hemos acabado, la fecha de D es superior a la de E, retorna 1. En caso contrario, los aos son iguales, y hemos de pasar al siguiente punto. 2. Comparamos en segundo lugar los meses de nacimiento. Si D.m < E.m, hemos acabado, la fecha de D es inferior a la de E, retorna -1. Si D.m > E.m, hemos acabado, la fecha de D es superior a la de E, retorna 1. En caso contrario, los meses son iguales, y hemos de pasar al siguiente punto. 3. Comparamos en ltimo lugar los das de nacimiento. Si D.d < E.d, hemos acabado, la fecha de D es inferior a la de E, retorna -1. Si D.d > E.d, hemos acabado, la fecha de D es superior a la de E, retorna 1. En caso contrario, las fecha son idnticas, retorna 0. En fin, debe ya resultar evidente lo que pretendemos, sea xuna estructura tipo d a t oy l = ( O ,O ,. . .,O )una lista ordenada, es decir: 1 2 n
O 1 O 2 O n

queremos insertar xen lde forma que la lista resultante est tambin ordenada. Un argumento de la funcin es la funcin de ordenacin, la cual ser un puntero a funcin, de forma que cambiando esta funcin, la lista pueda ordenarse por criterios distintos. El algoritmo es sencillo, pero exige una bsqueda previa, en concreto: 1. Si la lista les vaca, entonces l = ( x ) . 2. Si no, es decir, si la lista no es vaca, recorremos la lista hasta que encontremos el sitio adecuado para insertar el dato, concretamente, cuando x D, siendo D el dato actual. Para este apartado, necesitamos ir apuntando el nodo anterior, para hacer los enlaces correctamente. Tambin necesitamos un indicador para parar la bsqueda, cuando se encuentre el sitio. 3. Por ltimo, insertar el dato en ese lugar. Veamos un ejemplo aclaratorio, y para simplificar, imaginemos un orden numrico sobre la lista, la cual se representar por sus valores. Sea l = ( 7 ,1 5 ,2 8 ) , y el dato a insertar x = 1 9 . Recorremos la lista hasta que x D. Como 19 > 7 y 19 > 15, hay que parar en el tercer elemento, ya que 19 28. En este punto, el nodo anterior a n tes 15 y el nodo actual es D = p = 28, y si es qel nodo correspondiente a (19), entonces, antes de insertar:

Insertamos con las siguientes instrucciones:


a n t > s i g=q ; q > s i g=p ;

Es decir:

El algoritmo falla cuando no hay anterior, es decir, cuando a n t=N U L L . Cuando esto ocurre, la insercin es al comienzo, cuestin ya tratada en un apartado anterior. Observe que el algoritmo anterior tambin funciona cuando p = N U L L , es decir, cuando el objeto a insertar es al final de la lista. En este caso, las
personal.telefonica.terra.es/web/pegonrui/listas/listas.html 4/8

03/05/13

Listas enlazadas en C

sentencias:
a n t > s i g=q ; q > s i g=p ;

se convierten en:
a n t > s i g=q ; q > s i g=N U L L ;

lo cual es correcto. Finalmente, la funcin de insercin es:


/ * I n s e r t au nd a t oe nu n al i s t ao r d e n a d a . L an u e v al i s t ad e b eq u e d a ro r d e n a d a fe sl af u n c i nd eo r d e n a c i n * / s t r u c tl i s t a* i n s e r t a o r d e n a d o ( s t r u c tl i s t a* l ,s t r u c td a t ox ,i n t( * f ) ( s t r u c td a t oa ,s t r u c td a t ob ) ){ s t r u c tl i s t a* p , * q , * a n t ; i n ti n d ; q=c r e a n o d o ( ) ;/ *c r e au nn u e v on o d o* / q > d a t o s=x ;/ *c o p i a rl o sd a t o s* / q > s i g=N U L L ;/ *p o rd e f e c t o ,p u e d ec a m b i a r* / i f( l= =N U L L ){ l=q ; r e t u r nl ; } / *l al i s t an oe sn u l a* / a n t=N U L L ; p=l ; i n d=0 ; w h i l e( p! =N U L L& &i n d= =0 ){ i f( ( * f ) ( x , p > d a t o s )< =0 )/ *a q u h a yq u ei n s e r t a r* / i n d=1 ; e l s e{ a n t=p ; p=p > s i g ; } } i f( a n t= =N U L L ){/ *i n s e r c i na lc o m i e n z o* / q > s i g=l ; l=q ; }e l s e{/ *i n s e r c i ne nm e d i ooa lf i n a l* / a n t > s i g=q ; q > s i g=p ; } r e t u r nl ; }

Eliminar un objeto de la lista


En concreto, l = ( O ,O ,. . .,O )una lista y xuna estructura tipo d a t o , objeto que queremos borrar de la lista. Vamos a utilizar un 1 2 n procedimiento recursivo, en concreto: Si l = , no hay nada que borrar, retorna l . Si x = D , entonces, liberamos la memoria de O O ,. . .,O ) . 1 1y retornamos ( 2 n Si no, eliminamos xen ( O ,. . .,O ) . 2 n La funcin de borrado es:
s t r u c tl i s t a* e l i m i n a ( s t r u c tl i s t a* p ,s t r u c td a t ox ,i n t( * f ) ( s t r u c td a t oa ,s t r u c td a t ob ) ){ i n tc o n d ; i f( p= =N U L L )/ *n oh a yn a d aq u eb o r r a r* / r e t u r np ; / *c o m p a r ae ld a t o* /
personal.telefonica.terra.es/web/pegonrui/listas/listas.html 5/8

03/05/13

Listas enlazadas en C

c o n d=( * f ) ( x , p > d a t o s ) ; i f( c o n d= =0 ){/ *e n c o n t r a d o !* / s t r u c tl i s t a* q ; q=p > s i g ; f r e e ( p ) ;/ *l i b e r al am e m o r i ayh e m o sp e r d i d oe le n l a c e ,p o re s os eg u a r d ae nq* / p=q ;/ *r e s t a u r a rpa ln u e v ov a l o r* / }e l s e/ *n oe n c o n t r a d o* / p > s i g=e l i m i n a ( p > s i g , x , f ) ;/ *r e c u r r e* / r e t u r np ; }

Las versiones recursivas siempre son ms sencillas y elegantes que sus equivalentes iterativas. Un ejercicio interesante es programar la funcin anterior en forma iterativa.

Anular una lista


En concreto, sea l = ( O ,O ,. . .,O )una lista. Queremos empezar de nuevo, haciendo que l = N U L L . No basta con la ingenua instruccin: 1 2 n
l=N U L L ;

pues entonces, toda la memoria que le hemos pedido al sistema operativo se pierde para siempre. Por consiguiente, hay que devolver la memoria utilizada, con la siguiente funcin:
/ *a n u l au n al i s t al i b e r a n d ol am e m o r i a* / s t r u c tl i s t a* a n u l a l i s t a ( s t r u c tl i s t a* l ){ s t r u c tl i s t a* p , * q ; p=l ; w h i l e( p! =N U L L ){ q=p > s i g ;/ *p a r an op e r d e re ln o d o* / f r e e ( p ) ; p=q ; } r e t u r nN U L L ; }

y, por tanto, basta con escribir:


l=a n u l a l i s t a ( l ) ;

para que lsea la lista vaca.

Manejo del programa


Descargue listas.tgz y siga las siguientes instrucciones: Abra un emulador de terminal, por ejemplo x t e r m , y sitese en un directorio donde tenga permiso de escritura para practicar. Descomprima aqu el archivo descargado, introduciendo:
t a rz x v fl i s t a s . t g z

con lo que obtendr los fuentes l i s t a s . c , c o l a s . cyp i l a s . cy tres archivos de datos que son: d i e z p r i m e r o s . t x t ,d a t o s . t x ty g r a n d e . t x t que contienen 10, 20 y 164 personas respectivamente. Compile l i s t a s . c , para lo cual, introduzca:
c cl i s t a s . col i s t a s

No debe tener problemas con la compilacin, pues solamente se han utilizado funciones estndar del lenguaje C. La orden anterior crea el ejecutable l i s t a s . Este programa admite los siguientes argumentos:
h da r c h i v o d e -

Muestra una pequea ayuda en pantalla


6/8

personal.telefonica.terra.es/web/pegonrui/listas/listas.html

03/05/13
d a t o s aa n c h o d e p a n t a l l a

Listas enlazadas en C

Para cargar diferentes archivos de datos Para poder cambiar el ancho de pantalla, dependiendo de las capacidades del ambiente donde lo ejecute.

Si no introduce argumentos,por defecto, toma como archivo de datos d i e z p r i m e r o s . t x ty el ancho de pantalla en 80 caracteres. Veamos algunos ejemplos: El archivo de datos es d i e z p r i m e r o s . t x t , . / l i s t a s ancho de pantalla a 80 caracteres
. / l i s t a sdd a t o s . t x t . / l i s t a sdd a t o s . t x ta 1 4 0

El archivo de datos es d a t o s . t x t , ancho de pantalla a 80 caracteres El archivo de datos es d a t o s . t x t , ancho de pantalla a 140 caracteres

Los archivos de datos son una simulacin aleatoria de nombres de personas, dni y fecha de nacimiento. Como debe ser evidente, deben tener permisos de lectura, adems de estar preparados con el formato que exige el programa. Para comenzar a practicar y comprender los algoritmos, con el archivo de datos d i e z p r i m e r o s . t x tes suficiente, ya que la impresin en pantalla no ocupa mucho espacio y le ayuda a entenderlo todo. En fin, si las condiciones son las adecuadas, el programa leer los datos y crear una lista ordenada por fecha de nacimiento creciente. Observe la lnea dentro de main:
l=l e e d a t o s ( n o m f i c h , & i , c o m p a r a f e c h a ) ;

Si cambia el tercer argumento (puntero a funcin) puede obtener diferentes rdenes que son: c o m p a r a f e c h a Ordena la lista por orden creciente de fechas
c o m p a r a f e c h a i n v e r s aOrdena la lista por orden decreciente de fechas a l f a b e t i c a a l f a b e t i c a i n v e r s a

Ordena la lista por orden alfabtico creciente de nombres de personas Ordena la lista por orden alfabtico decreciente de nombres de personas

Como es evidente, cada vez que haga un cambio, debe volver a compilar el programa, ya que no se proporcionan opciones para hacerlo interactivamente. Por ltimo, el programa presenta un men en pantalla. Algunas opciones son: 1. Mostrar la lista grficamente . Se muestra en pantalla los datos ledos del archivo dentro de una caja de texto, imitando los nodos. 2. Insertar en la lista. Solicita el nombre de la persona, y para ello, no introduzca ms de 19 caracteres y sin espacios en blanco; el dni, mismo comentario al anterior, y la fecha de nacimiento, escrbala en la forma dia/mes/ao, escribiendo los separadores. Ejemplos vlidos son:
1 5 / 1 / 1 9 8 1 ,3 / 2 / 2 0 0 5 ,e t c .

Si cambia la funcin de ordenacin en l e e d a t o s , tambin debe cambiarla en la siguiente lnea (dentro de main):
l=i n s e r t a o r d e n a d o ( l , x , c o m p a r a f e c h a ) ;

para respetar el orden. 3. Borrar de la lista. Las celdas se borran por el nombre de la persona. El programa solicita el nombre de la persona. As pues, introduzca el nombre que quiere borrar. Si se encuentra, el nodo es borrado, en caso contrario, la lista queda igual. Finalmente, si encuentra algn error, comuniqumelo para su correccin.

Pilas y colas
Como ejemplo de aplicacin de listas, los dos programas p i l a s . cy c o l a s . c , incluidos en el paquete, son pequeas variaciones del principal l i s t a s . c , salvo que en las colas, la insercin de elementos es al final, y en las pilas, al principio. En ambos casos, las extracciones son al principio,
personal.telefonica.terra.es/web/pegonrui/listas/listas.html 7/8

03/05/13

Listas enlazadas en C

con la funcin:
/ *E x t r a ed a t oa lc o m i e n z od el al i s t a( p a r ap i l a syc o l a s )* / s t r u c tl i s t a* p o p ( s t r u c tl i s t a* l ,s t r u c td a t o* x ){ i f( l! =N U L L ){/ *n oh a c e rn a d as ile sn u l a* / s t r u c tl i s t a* p , * q ; p=l ; q=p > s i g ;/ *p a r an op e r d e re le n l a c e* / * x=p > d a t o s ;/ *c o p i a re ld a t o* / f r e e ( p ) ;/ *l i b e r am e m o r i a* / l=q ; r e t u r nl ; } }

El uso de ambos programas es idntico al de listas. Pedro Gonzlez Ruiz - Sevilla, junio 2010 Fecha de creacin: 26 de junio de 2010 Fecha de la ltima modificacin: 26 de junio de 2010 Volver a la pgina principal

personal.telefonica.terra.es/web/pegonrui/listas/listas.html

8/8

Você também pode gostar