Beruflich Dokumente
Kultur Dokumente
UNAN LEON
Departamento de Computacin
Ing. En Sistemas de Informacin
Docente: Ing. Karina Esquivel A.
Asignatura:
Algoritmo y Estructura de Datos.
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
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.
3.2.1
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.
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
3.2.2.1
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
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
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;
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;
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;
Grficamente, tenemos:
q = nuevo_elemento();
*q = *c;
c -> dato = x;
/*Valor Insertado*/
c -> siguiente = q;
Grficamente, sera:
3.2.2.3
De nuevo podemos encontrarnos con varios casos, segn la posicin del nodo a eliminar.
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.
q = c -> siguiente;
c -> siguiente = q -> siguiente;
free(q);
Grficamente, sera:
q = c->siguiente;
*c = *q;
free(q);
Grficamente, sera:
10
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
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
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
3.3
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
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
//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
/*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
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