Professional Documents
Culture Documents
Los programas usan estructuras de datos para almacenar informacin. Existen varias
estructuras de datos, por ejemplo listas, rboles, arreglos, o colas, para nombrar unos
pocos. Cada una de estas estructuras de datos pueden ser caracterizadas por su estructura y
sus mtodos de acceso.
Ejemplo:
Todos ustedes conocen las listas ligadas sencillas, las cules usan una estructura muy
simple, consistente en elementos que son empatados uno junto al otro
Las listas ligadas sencillas proveen solamente mtodos para aadir un elemento nuevo al
final y para suprimir el elemento del frente. Las estructuras de datos complejas pueden usar
estructuras ya existentes. Por ejemplo una cola puede ser estructurada como una lista ligada
sencilla. Sin embargo, las colas proveen mtodos de acceso para poner un elemento de
datos al final y para obtener el primer elemento de datos. (comportamiento first-in first-out
(FIFO), es decir, "primero-en-entrar-primero-en-salir")
Presentaremos ahora un ejemplo que usamos para presentar algunos conceptos de diseo.
Desde el momento que este ejemplo se usa solamente para ilustrar estos conceptos y
problemas, no es un ejemplo completo ni es el ptimo. Suponiendo que se quiera programar
una lista en un lenguaje de programacin modular tal como C o Modula-2. Como uno cree
que las listas pertenecen a una estructura de datos comn, decide implementarla en un
mdulo separado. Tpicamente, esto requiere que se escriban dos archivos: la definicin de
la interface y el archivo de implementacin. Usaremos un pseudo cdigo muy sencillo
/*
* Definicin de interface para un mdulo que implementa
* una lista ligada sencilla para almacenar datos de cualquier tipo.
*/
MODULE Singly-Linked-List-1
BOOL list_initialize();
BOOL list_append(ANY data);
BOOL list_delete();
list_end();
ANY list_getFirst();
ANY list_getNext();
BOOL list_isEmpty();
END Singly-Linked-List-1
Las definiciones de interfase solamente describen lo que est disponible pero no el cmo
sto se hace disponible. Se esconde la informacin de la implementacin en el archivo de
1
Plp 3
La idea de esta interfase es la siguiente: Antes de usar la lista, uno debe llamar a
list_initialize() para inicializar las variables locales a dicho mdulo. Los siguientes dos
procedimientos implementan los mtodos de acceso mencionados append y delete. El
procedimiento append necesita una discusin ms detallada. La funcin list_append() lleva
un argumento data de tipo arbitrario. Esto es necesario desde el momento que desea usar su
lista en varios ambientes diferentes, por lo tanto, el tipo de los elementos de datos a ser
almacenados en la lista no es conocido de antemano. Por consecuencia, debe usar un tipo
de datos especial ANY el cul permite asignarle datos de cualquier tipo. El tercer
procedimiento list_end() necesita ser llamado cuando el programa termina con el fin de
permitirle al mdulo limpiar sus variables usadas internamente. Por ejemplo, se puede
desear liberar la memoria asignada.
ANY data;
Se tiene ahora un mdulo de lista que permite usar la lista con cualquier tipo de elemento
de datos. Pero, Qu sucede si se necesita ms de una lista en uno de los programas ?
Si se decide redisear el mdulo de lista para que sea capaz de manejar ms de una lista. Se
crea una nueva descripcin de interfase que incluya una definicin para un manejador de
lista. Este manejador se usa en cada procedimiento provisto para identificar en forma
2
Plp 3
unvoca la lista en cuestin. El archivo de definicin de interfase del nuevo mdulo de lista
tiene el siguiente aspecto:
/*
* Un mdulo de lista para ms de una lista.
*/
MODULE Singly-Linked-List-2
DECLARE TYPE list_handle_t;
list_handle_t list_create();
list_destroy(list_handle_t this);
BOOL list_append(list_handle_t this, ANY data);
ANY list_getFirst(list_handle_t this);
ANY list_getNext(list_handle_t this);
BOOL list_isEmpty(list_handle_t this);
END Singly-Linked-List-2;
Se usa DECLARE TYPE para introducir un nuevo tipo list_handle_t el cul representa tu
manejador de lista. No especificamos como este manejador est realmente representado o
an implementado. Tambin se esconde los detalles de la implementacin de este tipo de
datos en el archivo de implementacin. Ntese la diferencia con la versin anterior en la
cul solamente esconde funciones o procedimientos, respectivamente. Ahora, tambin
esconde la informacin de un tipo de datos definido por el usuario llamado list_handle_t.
Se usa list_create() para obtener un manejador a una nueva (y por lo mismo vaca) lista.
Cada uno de los otros procedimientos contiene el parmetro especial this el cul solamente
identifica la lista en cuestin. Todos los procedimientos operan ahora sobre este manejador
en lugar de operar sobre una lista global modular.
Podra decirse ahora, que se puede crear objetos lista. Cada uno de tales objetos puede ser
unvocamente identificado por su manejador y solamente se les pueden aplicar aquellos
mtodos que son definidos para operar sobre este manejador.
En el ejemplo, cada vez que se quiere usar una lista, tiene que declarar explcitamente un
manejador y hacer una llamada a list_create() para obtener un manejador de lista vlido.
3
Plp 3
Despus del uso de la lista, debe llamar explcitamente a list_destroy() con el manejador de
la lista que quieres que se destruya. Si quieres usar una lista dentro de un procedimiento,
digamos, foo() , usas el siguiente esqueleto de cdigo:
PROCEDURE foo() BEGIN
list_handle_t myList;
myList <- list_create();
list_destroy(myList);
END
Comparemos la lista con otros tipos de datos, por ejemplo un entero. Los enteros se
declaran dentro de un mbito particular (por ejemplo, dentro de un procedimiento). Una vez
que los ha definido, puede usarlos. Una vez que abandona el mbito (el procedimiento
donde fue definido el entero, por ejemplo) el entero se pierde. Se crea y se destruye
automticamente. Algunos compiladores tambin inicializan los enteros recin creados con
un valor, tpicamente 0 (cero)
Cul es la diferencia con lo "objetos" tipo lista ? La vida de una lista tambin est definida
por su mbito, por lo tanto, debe crearse una vez que se entra al mbito y destruirse una vez
que se abandona. En el momento de su creacin, una lista debera inicializarse vaca. Por
consiguiente, nos gustara poder definir un lista en forma similar a la definicin de un
entero. Un esqueleto de cdigo para esto se vera del siguiente modo:
PROCEDURE foo() BEGIN
list_handle_t myList; /* La lista es creada e inicializada */
4
Plp 3
En orientacin a objetos, la estructura se organiza por los datos. Uno escoge las
representaciones de datos que mejor se ajusten a tus requerimientos. Por consecuencia, sus
programas se estructuran por los datos ms que por las operaciones. As, esto es
exactamente del otro modo: Los datos especifican las operaciones vlidas. Ahora, los
mdulos agrupan representaciones de datos en forma conjunta.
En nuestro ejemplo de la lista, tenemos que usar un tipo especial ANY para permitir a la
lista contener cualquier dato que gustemos.
sto implica que el compilador no puede garantizar la consistencia de los tipos de datos.
...
list_destroy(myList);
END
Lo que quisiramos tener es un mecanismo que nos permita especificar sobre que tipos de
datos debera ser definida la lista. La funcin total de la lista es siempre la misma, sin
importar si almacenamos manzanas, nmeros, autos o an listas. Por lo tanto, sera bueno
declarar una nueva lista con algo como esto :
list_handle_t<Apple> list1; /* una lista de manzanas */
list_handle_t<Car> list2; /* una lista de carros */
5
Plp 3
Estrategias y representacin
Para una estructura de datos simple como la lista sencilla ligada, uno puede pensar en
nicamente una estrategia de recorrido. Empezando con el elemento ms hacia la izquierda,
uno visita sucesivamente los vecinos de la derecha hasta que se alcanza el ltimo elemento.
Sin embargo, estructuras de datos ms complejas tales como los rboles, pueden ser
recorridos usando diferentes estrategias. Peor an, algunas veces las estrategias de recorrido
dependen del contexto particular en el que se usa la estructura de datos. Consecuentemente, tiene
sentido el separar la representacin o forma de la estructura de datos de su estrategia de recorrido.
Lo que hemos mostrado con la estrategia de recorrido se aplica a otras estrategias por igual.
Por ejemplo, la insercin de un elemento puede ser hecha de modo tal que se realice un
ordenamiento de elementos o se deje de hacer esto ltimo.
As, en los primeros tiempos de los lenguajes de programacin de alto nivel all por los
aos setenta, el paradigma dominante era la Programacin Procedural. La idea bsica era
establecer los procedimientos, las funciones, que resolvan el problema, es decir, buscar los
algoritmos que resolvan el problema. El exponente clsico de este tipo de programas es
FORTRAN, si bien, PASCAL o C son tambin lenguajes que utilizar parte de esa filosofa.
Con el paso del tiempo los programas fueron creciendo y el ncleo de los programas paso a
ser los datos mas que los procedimientos. As surgi un nuevo paradigma denominado
Programacin Modular. Su principio es establecer mdulos que trabajen con los mismos
datos, de forma que <<escondan>> La complejidad del tratamiento de esos datos a otros
mdulos. La aportacin bsica de este paradigma a la programacin fue el concepto de
modulo, del que hacen uso por ejemplo, Modula-2 o el propio C a travs de las bibliotecas
de funciones.
El trabajo con estos mdulos especializados en un determinado tipo de datos hizo surgir
tambin la necesidad de estructurar esos tipos de datos. De esa forma, se dispona de
instrucciones para definir estructuras de datos, a travs de mecanismos como el struct de C
o el record de Pascal.
6
Plp 3
Por ejemplo, en C se puede crear un tipo de datos que represente a una persona de la
siguiente forma:
struct Persona {
Char nombre[15];
char apellidos[25];
int DNI[8]; }
A esta conjuncin del tipo de datos con las funciones que lo manejan se le conoce como el
paradigma de la Abstraccin de Datos. C tambin soporta, como se acaba de ver, este
paradigma mediante las estructuras y las bibliotecas de funciones.