Sie sind auf Seite 1von 16

2010

UNAN LEON
Departamento de Computacin
Ing. En Sistemas de Informacin
Docente: Ing. Karina Esquivel A.
Asignatura:
Algoritmo y Estructura de Datos.

ESTRUCTURAS DINMICAS DE DATOS


(LISTAS)

Estructuras Dinmicas de Datos

TEMA 3: ESTRUCTURAS DINMICAS DE DATOS


(LISTAS)
3.1

INTRODUCCIN:

Las estructuras dinmicas nos permiten crear estructuras de datos que se adapten a las necesidades
reales a las que suelen enfrentarse nuestros programas. A travs de estas podremos crear
estructuras de datos muy flexibles, en cuanto al orden, la estructura interna o las relaciones entre
los elementos que las componen.
Las estructuras de datos estn compuestas de otras pequeas estructuras a las que llamaremos
nodos o elementos, que agrupan los datos con los que trabajar nuestro programa y adems uno o ms
punteros autoreferenciales, es decir, punteros a objetos del mismo tipo.
Dentro de los datos de este tipo de datos podemos hablar de:

Listas.

Pilas.

Colas.

rboles.

3.2

LISTA LINEAL ENLAZADA:

Una lista lineal enlazada es un conjunto de elementos u objetos de cualquier tipo, originariamente
vaca que, durante la ejecucin del programa va creciendo o decreciendo elemento a elemento segn
las necesidades previstas. En una lista lineal cada elemento apunta al siguiente, es decir, cada
elemento tiene informacin de dnde esta el siguiente. Por este motivo tambin se le llama lista
enlazada.
La forma ms simple de estructura dinmica es la lista enlazada. 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 lineales 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.
Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista est vaca.

Estructuras Dinmicas de Datos

El nodo tpico para construir listas tiene esta forma:


struct nodo
{
int dato;
struct nodo *siguiente;
};
En el ejemplo, cada elemento de la lista slo contiene un dato de tipo entero, pero en la prctica no
hay lmite en cuanto a la complejidad de los datos a almacenar.
Dependiendo del nmero de punteros y de las relaciones entre nodos, podemos distinguir varios tipos
de estructuras dinmicas:

LISTAS SIMPLEMENTE ENLAZADA (o abiertas): Cada elemento (nodo) slo dispone de un
puntero, que apuntar al siguiente elemento de la lista o valdr NULL si es el ltimo elemento. Slo se
pueden recorrer hacia delante.

PILAS: Son un tipo especial de lista, conocidas como listas LIFO (Last In, First Out): el
ltimo en entrar es el primero en salir). Los elementos se "amontonan" o apilan, de modo que slo el
elemento que est encima de la pila puede ser ledo, y slo pueden aadirse elementos encima de la
pila.

COLAS: Otro tipo de listas, conocidas como listas FIFO (First In, First Out: El primero en
entrar es el primero en salir). Los elementos se almacenan en fila, pero slo pueden aadirse por un
extremo y leerse por el otro.

LISTAS CIRCULARES: Tambin llamadas listas cerradas, son parecidas a las listas
enlazadas, pero el ltimo elemento apunta al primero. De hecho, en las listas circulares no puede
hablarse de "primero" ni de "ltimo". Cualquier nodo puede ser el nodo de entrada y salida. Se
recorren siempre en el mismo sentido.

LISTAS DOBLEMENTE ENLAZADAS: Cada elemento dispone de dos punteros, uno apunta al
siguiente elemento y el otro al elemento anterior. Al contrario que las listas abiertas anteriores,
estas listas pueden recorrerse en los dos sentidos.

3.2.1

LISTAS SIMPLEMENTE ENLAZADAS:

La forma ms simple de estructura dinmica es la lista simplemente enlazada o 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:

La anterior es una lista simplemente enlazada que consta de 4 elementos (nodos).

Estructuras Dinmicas de Datos

Para crear una lista debemos definir la clase de elementos que van a formar parte de la misma. Un
tipo de dato genrico podra ser la siguiente estructura:
struct nodo
{
int dato;
struct nodo *sig;
};
El miembro de la estructura "sig", puede apuntar a un objeto del tipo nodo. De este modo, cada nodo
puede usarse como un ladrillo para construir listas de datos, y cada uno mantendr ciertas relaciones
con otros nodos.
En el ejemplo, cada elemento de la lista slo contiene un dato de tipo entero, pero en la prctica no
hay lmite en cuanto a la complejidad de los datos a almacenar. Se pueden disear datos struct que
acten como nodos tan complejos como se desee.
El nodo anterior se representar as (no consideramos el miembro datos, slo el miembro sig, que
ahora apunta a NULL.

Para acceder a un nodo de la estructura slo necesitaremos un puntero a un nodo. En el ejemplo


anterior declaramos una variable de estructura, que va a ser un puntero a dicha estructura.
Mediante typedef declaramos un nuevo tipo de dato:
typedef struct nodo
{
int dato;
struct nodo *siguiente;
} elemento;
elemento *c; //puntero a nodo
Ahora elemento es un tipo de dato, sinnimo de struct nodo. El miembro siguiente ha sido declarado
como puntero al dato struct nodo y no como puntero a tipo de dato elemento, ya que en ese instante,
elemento no estaba an definido.
Por tanto, elemento es el tipo para declarar nodos. Ahora es un tipo de dato. La variable *c es un
puntero al tipo de dato elemento.

Estructuras Dinmicas de Datos

En las listas simples enlazadas existe un nodo especial: el primero. Normalmente diremos que nuestra
lista es un puntero a ese primer nodo y llamaremos a ese nodo cabeza de la lista. Eso es porque
mediante ese nico puntero podemos acceder a toda la lista.
Nota: 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 utilizar la informacin almacenada ni liberar el espacio de memoria que ocupa.
Cuando el puntero que usamos para acceder a la lista vale NULL, diremos que la lista est vaca:
*c = NULL; //lista vaca
Inicialmente *siguiente apunta a NULL. Lo representamos grficamente en la forma:

3.2.2

OPERACIONES BSICAS CON LISTAS:

Con las listas se pueden realizar las siguientes operaciones bsicas:


a) Crear lista.
b) Aadir o insertar elementos.
c) Buscar o localizar elementos.
d) Borrar elementos.
Cada una de estas operaciones tendr varios casos especiales, por ejemplo, no ser lo mismo insertar
un nodo en una lista vaca, o al principio de una lista no vaca, o la final, o en una posicin intermedia.

3.2.2.1

CREAR UNA LISTA

Si queremos crear una lista, podemos emplear la tcnica de reservar memoria dinmicamente. Para
ello escribimos una funcin llamada nuevo_elemento():
elemento *nuevo_elemento(void)
{
elemento *q;
q = (elemento *)malloc(sizeof(elemento));
if(q == NULL)
puts(No se ha reservado memoria para el nuevo nodo);
return q;
//devuelve la direccin del espacio de memoria reservado
}
Cada vez que deseemos crear un nuevo nodo, debemos llamar a la funcin nuevo_elemento() para
realizar la reserva de memoria.
5

Estructuras Dinmicas de Datos

Ejemplo #1: Cdigo C que permite crear una lista asignando memoria de forma dinmica.
//crear_lista.c
#include<stdio.h>
elemento *nuevo_elemento(void)
{
elemento *q;
q = (elemento *)malloc(sizeof(elemento));
if(q == NULL)
puts(No se ha reservado memoria para el nuevo nodo);
return q;
//devuelve la direccin del espacio de memoria reservado
}
void main()
{
elemento *q;
q = NULL;
q = nuevo_elemento();
q->siguiente = NULL;

//puntero a un nodo
//lista vaca
//q apunta al nodo recin creado
//fin de lista

//operaciones. . .
//Liberacin de memoria reservada
free(q);
}
Grficamente:

3.2.2.2

AADIR O INSERTAR ELEMENTOS EN UNA LISTA ENLAZADA


Insertar un elemento en una lista vaca: Este es el caso ms sencillo. Equivale a crear una
lista, como en el caso anterior. Partiremos de que ya tenemos el nodo a insertar (creado en la llamada
a la funcin nuevo_elemento() ) 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 se realice lo siguiente:
q = nuevo_elemento();
q->siguiente = NULL;

Estructuras Dinmicas de Datos

Grficamente:


Insertar un elemento en la primera posicin de una lista: Podemos considerar el caso
anterior como un caso particular de ste, la nica diferencia es que en el caso anterior la lista es una
lista vaca, pero siempre podemos, y debemos considerar una lista vaca como una lista. Por tanto,
ahora la lista ya existe. De nuevo partiremos de un nodo a insertar, con un puntero que apunte a l
(q=nuevo elemento()), y de una lista en este caso no vaca, apuntada por c:
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = nuevo_elemento();
q->dato = valor;
q->siguiente = c;
c = q;

Es fundamental no alterar el orden de las operaciones.


Grficamente, tenemos:


Insertar un elemento en general: La insercin de un elemento en la lista, a continuacin de
otro elemento apuntado por c, es de la forma siguiente:
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = nuevo_elemento();
q->dato = x;
/*Valor insertado */
q->siguiente = c->siguiente;
c->siguiente = q;

Estructuras Dinmicas de Datos

Grficamente, tenemos:

Insercin en la lista detrs del elemento apuntado por c.



La insercin de un elemento en la lista antes de otro elemento apuntado por c, se hace
insertado un nuevo elemento detrs del elemento apuntado por c, intercambiando previamente los
valores del nuevo elemento y del elemento apuntado por c.
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = nuevo_elemento();
*q = *c;
c -> dato = x;
/*Valor Insertado*/
c -> siguiente = q;

Grficamente, sera:

Insercin en la lista antes del elemento apuntado por c.

Estructuras Dinmicas de Datos

3.2.2.3

BORRAR ELEMENTOS DE UNA LISTA ENLAZADA:

De nuevo podemos encontrarnos con varios casos, segn la posicin del nodo a eliminar.


Eliminar el primer nodo de una lista enlazada: Es el caso ms simple.


o Partiremos de una lista con uno o ms nodos, y usaremos un puntero auxiliar, q:
o Hacemos que q apunte al primer elemento de la lista, es decir a c.
o Asignamos a c la direccin del segundo nodo de la lista: c = c->siguiente.
o Liberamos la memoria asignada al primer nodo, q, el que queremos eliminar: free(q);

Si no guardamos el puntero al primer nodo antes de actualizar c, despus nos resultara imposible
liberar la memoria que ocupa. Si liberamos la memoria antes de actualizar c, perderemos el puntero al
segundo nodo.
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c;
c = c->siguiente; //Actualizar el comienzo de la lista
free(q);
Si la lista slo tiene un nodo, el proceso es tambin vlido, ya que el valor de c->siguiente es NULL, y
despus de eliminar el primer nodo la lista quedar vaca, y el valor de c ser NULL. De hecho, el
proceso que se suele usar para borrar listas completas es eliminar el primer nodo hasta que la lista
est vaca.
Grficamente, sera:


Eliminar un nodo cualquiera de una lista enlazada: En todos los dems casos, eliminar un
nodo se puede hacer siempre del mismo modo. Supongamos que tenemos una lista con al menos dos
elementos, y un puntero c al nodo anterior al que queremos eliminar. Y un puntero auxiliar q.
Si el nodo a eliminar es el ltimo, el procedimiento es igualmente vlido, ya que c pasar a ser el
ltimo, y c->siguiente valdr NULL.

Estructuras Dinmicas de Datos

El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c -> siguiente;
c -> siguiente = q -> siguiente;
free(q);
Grficamente, sera:

Borrar el sucesor del elemento apuntado por c




Eliminar un elemento apuntado por c:

El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c->siguiente;
*c = *q;
free(q);
Grficamente, sera:

Borrar el elemento apuntado por c



Borrar todos los elementos de una lista: Equivale a liberar la memoria reservada para cada
uno de los elementos de la misma. Si el primer nodo est apuntado por c, empleamos el puntero
auxiliar q:

10

Estructuras Dinmicas de Datos

El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c;
//salvamos el puntero a la lista
while(q != NULL)
{
c = c->sig;
free(q);
q = c;
}
Hay que observar que antes de borrar el elemento apuntado por q, hacemos que c apunte al siguiente
elemento ya que si no perdemos el resto de la lista.

3.2.2.4

RECORRIDO DE UNA LISTA CUYO PRIMER ELEMENTO EST APUNTADO


POR c.

Supongamos que hay que realizar una operacin con todos los elementos de una lista, cuyo primer
elemento est apuntado por c. Por ejemplo, escribir el valor de cada elemento de la lista. La secuencia
de operaciones es la siguiente:
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c;
/*salvamos el puntero al comienzo de la lista*/
while(q !=NULL)
{
printf(%d,q->dato);
q = q->siguiente;
}
3.2.2.5

BUSCAR UN ELEMENTO CON UN VALOR x DENTRO DE LA LISTA


ENLAZADA.

La bsqueda es secuencial y termina cuando se encuentra el elemento, o bien, cuando se llega al final
de la lista.
El fragmento de cdigo en lenguaje C que explica el proceso es:

q = c;
printf(Que valor desea buscar en la lista?);
scanf(%d,&x);
while(q != NULL && q->dato != x)
q = q->siguiente;

11

Estructuras Dinmicas de Datos

3.3

EJEMPLO COMPLETO DE LISTA LINEAL ENLAZADA:

Programa que nos permita crear una lista clasificada, en la cual cada elemento conste
de dos campos: uno que contenga un nmero entero y otro que sea un puntero a un
elemento del mismo tipo.
El programa incluir las siguientes funciones:
1. Aadir un elemento. Esta funcin comprender dos casos: insertar un elemento al principio de la
lista o insertar un elemento despus de otro.
2. Borrar un elemento de la lista. Esta funcin buscar el elemento a borrar y despus lo borrar.
Hay que distinguir si se trata de la cabecera o de un elemento cualquiera.
3. Buscar un elemento en la lista.
4. Visualizar el contenido de la lista.
/****************** Operaciones con listas **********************/
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include<string.h>
#define ListaVacia (cabecera==NULL)
/*Lista simplemente enlazada. Cada elemento contiene un n entero*/
typedef struct datos elemento;
/*declaracin del tipo elemento*/
struct datos
/*elemento de una lista de enteros*/
{
int dato;
elemento *siguiente;
};
/*Funciones prototipos*/
elemento *NuevoElemento(void);
void error(void);
void menu(void);
void anadir(elemento **, int);
void borrar(elemento **, int);
elemento *buscar(elemento *, int);
void visualizar(elemento *);
/*Funcin principal*/
void main()
{
elemento *cabecera = NULL;
elemento *q;
int opcion, dato, k = 10;

12

Estructuras Dinmicas de Datos

while(1)
{
do
{
system("cls");
menu();
opcion = getchar();
}while(opcion < '1' || opcion > '5');
system("cls"); // Limpiar Pantalla
switch(opcion)
{
case '1':
printf("Insertar datos: ");
scanf("%d",&dato);
anadir(&cabecera,dato);
break;
case '2':
printf("Borrar dato: "); scanf("%d",&dato);
borrar(&cabecera,dato);
break;
case '3':
printf("Buscar dato: ");
scanf("%d",&dato);
q = buscar(cabecera,dato);
if(q)
q->dato+=k;
else
printf("Lista vacia\n");
break;
case '4':
visualizar(cabecera);
break;
case '5':
exit(0);
}
printf("\nPulse una tecla para continuar");
getchar();
}
}

13

Estructuras Dinmicas de Datos

//Definicin de Funciones
/* Crear un nuevo elemento */
elemento *NuevoElemento(void)
{
elemento *q = (elemento *)malloc(sizeof(elemento));
return (q);
}
/* Funcin Error */
void error (void)
{
perror ("Error: insuficiente espacio de memoria.\n");
exit (-1);
}
/* Funcin Men */
void menu()
{
printf("\n\t1. Insertar un elemento\n");
printf("\n\t2. Borrar un elemento\n");
printf("\n\t3. Buscar un elemento\n");
printf("\n\t4. Vizaualizar la lista\n");
printf("\n\t5. Salir\n");
printf("\nElija la opcion deseada:\n");
}
/* Introducir un elemento ordenadamente en la lista */
void anadir(elemento **cab, int dato)
{
elemento *cabecera = *cab;
elemento *actual = cabecera,*anterior = cabecera, *q;
if (ListaVacia) /*Si la lista esta vaca, crear un nuevo elemento*/
{
cabecera = NuevoElemento();
cabecera->dato = dato;
cabecera->siguiente = NULL;
*cab=cabecera;
return;
}
/*Entrar en la lista y encontrar el punto de insercin*/
while(actual != NULL && dato > actual->dato)
{
anterior = actual;
actual = actual->siguiente;
}
14

Estructuras Dinmicas de Datos

/*Dos casos:
*1) Insertar al principio de la lista
*2) Insertar despus de anterior (incluye insertar al final)*/
q = NuevoElemento(); /*se genera un nuevo elemento*/
if(anterior == actual) /*insertar al principio*/
{
q->dato = dato;
q->siguiente = cabecera;
cabecera = q;
}
else /*insertar despus de anterior*/
{
q->dato = dato;
q->siguiente = actual;
anterior->siguiente = q;
}
*cab = cabecera;
}
/* Encontrar un dato y borrarlo */
void borrar(elemento **cab, int dato)
{
elemento *cabecera = *cab;
elemento *actual = cabecera, *anterior = cabecera;
if (ListaVacia)
{
printf("Lista Vacia\n");
return;
}
/*entrar en la lista y encontrar el elemento a borrar*/
while(actual !=NULL && dato != actual->dato)
{
anterior = actual;
actual = actual->siguiente;
}
/*si el dato no se encuentra retornar*/
if(actual == NULL)
return;
/*si el dato se encuentra, borrar el elmento*/
if(anterior == actual) /*borrar el elemento de cabecera*/
{
cabecera = cabecera->siguiente;
}

15

Estructuras Dinmicas de Datos

else
{
anterior->siguiente = actual->siguiente;
}
free(actual);
*cab = cabecera;
}
/* Buscar un elemento determinado en la lista */
elemento *buscar(elemento *cabecera, int dato)
{
elemento *actual = cabecera;
while(actual != NULL && dato != actual->dato)
actual = actual->siguiente;
return (actual);
}
/* Visualizar la lista */
void visualizar(elemento *cabecera)
{
elemento *actual = cabecera;
if (ListaVacia)
printf("Lista Vaica\n");
else
{
while(actual != NULL)
{
printf("%d ",actual->dato);
actual = actual->siguiente;
}
printf("\n");
}
}

16

Das könnte Ihnen auch gefallen