estructuras básicas

Anuncio
8
ESTRUCTURAS BÁSICAS
8.1. Concepto de datos estructurados.
En temas anteriores vimos la representación de los datos en un computador y los distintos
tipos que hay: carácter (ASCII), real (o de coma flotante), entero (o coma fija) y lógico
(verdadero o falso). En esta lección, vamos a ver los distintos modos en que pueden agruparse
estas clases de datos para formar lo que denominamos estructuras de datos, que nos permiten
utilizar grandes volúmenes de datos de forma más sencilla.
Una estructura de datos, o un tipo de datos estructurado, es un tipo de dato construido a
partir de otros. Un dato de tipo estructurado está compuesto por una serie de datos de tipos
elementales y alguna relación existente entre ellos. Normalmente, la relación suele ser de orden
aunque puede ser de cualquier otro tipo.
Se dice que una estructura de datos que es homogénea cuando todos los datos elementales
que la forman son del mismo tipo. En caso contrario, se dice que la estructura es heterogénea.
Por ejemplo, el tipo de datos complejo es una estructura homogénea, tanto la parte real como la
imaginaria se representan con datos reales.
Siempre que se utilice un dato en un programa debe estar determinado su tipo, para que el
traductor sepa como debe tratarlo y almacenarlo. En el caso de datos de tipos elementales, el tipo
de dato determina el espacio que se utiliza en memoria. Esto, puede no ocurrir si el dato es de un
tipo estructurado.
Una estructura de datos que siempre ocupa el mismo espacio en memoria, se dice que es
estática. Por el contrario, si la memoria asignada a una determinada estructura de datos va
variando durante la ejecución del programa, es decir, se realiza una asignación dinámica de
memoria, se dice que es una estructura de datos dinámica.
131
Apuntes de Informática
8.2. Estructuras de datos estáticas.
Dentro de los tipos de estructuras de datos que ocupan siempre el mismo espacio en memoria
tenemos los punteros, las cadenas y los arrays.
8.2.1. Punteros.
Un puntero es un dato que indica la posición de otro dato. Su utilidad se pone de manifiesto
en la construcción de estructuras de datos, ya que son ellos los que proporcionan los lazos de
unión entre los elementos que constituyen las estructuras. Son importantes los punteros al
principio y al final de la estructura.
Si, ocasionalmente, se necesita que un puntero no señale a ningún dato, se dice que el
puntero tiene un valor nulo (puntero nulo).
8.2.2. Cadenas.
Una cadena es una secuencia de caracteres que se interpretan como un dato único. Las
cadenas pueden tener longitud fija o variable. La longitud de la cadena se indica tanto por el
número de caracteres que contiene ésta, indicado al principio de la misma, como por un carácter
especial denominado fin-de-cadena. Sobre datos de tipo cadena se pueden realizar las siguientes
operaciones:
♦ Concatenación: Consiste en formar una cadena a partir de dos ya existentes, juntando
los caracteres de ambas.
♦ Extracción de subcadena: Permite formar una cadena a partir de otra ya existente. La
subcadena se forma tomando un tramo consecutivo de la cadena inicial.
♦ Comparación de cadenas: Es posible comparar dos cadenas. Se considera menor
aquella en que el primer carácter en que difieren ambas es menor.
♦ Obtención de la longitud: La longitud de una cadena es un dato de tipo entero, cuyo
valor es el número de caracteres que contiene ésta.
8.2.3. Arrays.
El array (también llamado formación o matriz), es la estructura de datos más usual. Existe en
todos los lenguajes de programación y en algunos es de las pocas estructuras de datos existentes
(BASIC y FORTRAN).
132
TEMA 8 – Estructuras básicas
Un array es una estructura de datos formada por una cantidad fija de datos del mismo tipo,
cada uno de los cuales tiene asociado uno, o más índices, que determinan de forma unívoca la
posición del dato en el array.
Podemos imaginar un array como una estructura de celdas donde se pueden almacenar
valores. En la figura podemos ver una matriz de un sólo índice que toma valores de 1 a 7.
En el array de la figura siguiente utilizamos dos índices con valores entre 1 y 3, el primero, y
entre 1 y 5, el segundo. Cada elemento de esta matriz está representado por un par ordenado de
números, el valor de los dos índices.
En general, al número de índices del array se le denomina número de dimensiones del array.
La dimensión de la formación está dada por los valores máximos de los índices y, el número total
de elementos es el producto de estos valores máximos. En los dos ejemplos anteriores, el número
de dimensiones de los arrays son 1 y 2, las dimensiones son (7) y (3; 5) y los números totales de
elementos son 7 y 15, respectivamente.
La principal operación que se puede realizar con los arrays es la selección, que consiste en
especificar un elemento determinado del array. Esta operación se efectúa dando un valor para
todos y cada uno de los índices del array. Con el elemento seleccionado se pueden realizar las
operaciones propias de su tipo. Así, con cada elemento de un array real, una vez seleccionado, se
pueden realizar las operaciones definidas para datos de tipo real (operaciones aritméticas).
8.3. Estructuras dinámicas de datos.
Como ya se ha dicho, este tipo de estructuras ocupan un espacio en memoria que va
evolucionando según el tamaño que dicha estructura vaya adquiriendo. Las estructuras de dinámicas
que vamos a estudiar son: colas, pilas, listas encadenadas y árboles.
8.3.1. Colas (FIFO).
Una cola es una estructura de datos en la que el primer dato en entrar es el primer dato en
salir. Es decir, es una estructura FIFO (First In First Out). Todo el mundo conocemos como
133
Apuntes de Informática
funciona una cola, los nuevos se ponen al final, los servicios se prestan al principio y no está
permitido “colarse”. Las mismas reglas se aplican a las colas de datos almacenadas en la
memoria de un computador.
Hay varias formas de implementar una cola en la memoria de un computador. Una forma
simple consiste en almacenar los datos en posiciones de memoria adyacentes y utilizar punteros
para el principio y el fin de la cola. Cuando un elemento se añade a la cola, el puntero de la parte
posterior se ajusta para que señale al nuevo elemento. De manera similar, cuando un elemento se
elimina de la cola, se ajusta el puntero delantero para que señale al nuevo primer elemento.
El problema de este método para implementar las colas es que las posiciones de memoria que
ocupan, varían a medida que se añaden y eliminan elementos de la misma. La solución habitual
consiste en asignar un área fija para almacenar la cola y permitir que se mueva en este área de
manera circular. Un área de almacenamiento de esta forma se denomina buffer circular , y puede
apreciarse en la figura siguiente.
Entre las aplicaciones que tienen las colas se encuentran el almacenamiento de datos en
camino, entre un procesador y un periférico, o actuar como punto intermedio en las redes de
comunicación de datos.
8.3.2. Pilas (LIFO).
Una pila es una colección ordenada de datos a los que sólo se puede acceder por un extremo,
denominado tope o cima de la pila. La pila es una estructura en la que el último elemento en
entrar será el primero en salir, es decir, es lo que se denomina estructura LIFO (Last In First
Out).
134
TEMA 8 – Estructuras básicas
Podemos comparar esta estructura con una pila de platos colocada sobre un muelle. Cuando
se añade un nuevo plato en lo alto de la pila, los demás bajan, cuando se retira un plato de la pila,
los demás suben.
Igual que en el caso de las colas, van a existir dos punteros, uno que indica la posición tope
de la pila, denominado puntero de pila, y otro que señala su base, denominado base de pila, y
que mantiene el mismo valor mientras existe la pila. Cuando la pila esta vacía el puntero de pila
tiene el mismo valor que la base de pila.
La pila es una de las estructuras más importantes en computación. Se usa en cálculos, para
pasar de un lenguaje de computador a otro y, para transferir el control de una parte del programa
a otra.
Las operaciones que se pueden realizar tanto con las colas como con las pilas, son las
siguientes:
•
Añadir o eliminar un elemento: Si es una cola podremos añadirlo o eliminarlo al final
de la misma, y si es una pila al principio.
•
Acceder al primer elemento: Normalmente es el único al que se va a poder acceder
directamente.
•
Acceder al elemento siguiente del último procesado: Este es el mecanismo normal de
acceso tanto a colas como a pilas.
•
Saber si está vacía: Están vacías si no contienen ningún elemento.
8.3.3. Listas encadenadas.
Una lista es un conjunto ordenado de datos. Los elementos de la lista pueden insertarse o
eliminarse en cualquier punto de la misma, por lo que es menos restrictiva que una pila o una
cola.
La forma más sencilla de implementar una lista es hacer uso de un puntero que señale desde
un dato al siguiente. También hay un puntero que señala al primer elemento de la lista, mientras
que para el último se emplea un puntero nulo.
Una estructura de este tipo se denomina lista encadenada. Cada elemento de la lista consiste
en una parte de datos y un puntero.
Una variación sobre la idea de una lista es el caso en el que el puntero del final de la lista
señale al primer elemento. Esto crea lo que se denomina una lista circular.
Si los elementos de la lista están en orden alfabético o numérico, dichas listas se conocen
como listas ordenadas.
135
Apuntes de Informática
8.3.4. Árboles.
Un árbol es una estructura que implica una jerarquía, en la que cada elemento está unido a
otros bajo él. Cada dato en un árbol es un nodo de dicho árbol. El nodo más alto se denomina
raíz. Cada nodo puede estar conectado a uno o más subárboles, que también responden a la
estructura de un árbol. Un nodo, en la parte inferior, del que no cuelgue ningún subárbol se
denomina nodo terminal u hoja.
Un tipo especial de árboles muy usados en computación son los árboles binarios. En ellos, de
cada nodo pueden colgar, a lo más, dos subárboles, denominados subárbol derecho y subárbol
izquierdo, que también son árboles binarios.
La forma usual de representar los árboles supone el uso de punteros. En un árbol binario cada
nodo está constituido por una parte de datos y dos punteros. Uno, o ambos punteros, pueden
tener un valor nulo si del nodo no cuelgan subárboles.
Son muy utilizados en informática. Las partes de muchos programas se enlazan como si se
tratara de árboles. Los árboles se utilizan para representar operaciones aritméticas, y en
búsquedas y ordenaciones.
8.4. Estructura de archivos.
Un archivo no es más que una estructura de datos y, por tanto, podrían haberse incluido en el
apartado anterior. Pero debido a la importancia que tienen les dedicaremos una atención especial.
8.4.1. Concepto de archivo.
Los datos que se encuentran en la memoria masiva (discos magnéticos, discos ópticos, etc.)
suelen organizarse en archivos.
Un archivo es un conjunto de información sobre un mismo tema, tratada como una unidad de
almacenamiento y organizada de forma estructurada para la búsqueda de un dato individual. Un
archivo está compuesto de registros homogéneos que contienen información sobre el tema.
La vida de todo archivo comienza cuando se crea y acaba cuando se destruye o borra.
Durante la vida del archivo se suelen realizar sobre él determinadas operaciones, de
recuperación o consulta y, de mantenimiento o actualización. Las operaciones de actualización
que se pueden realizar sobre el archivo son:
•
Modificación de un registro.
•
Eliminación o borrado de un registro.
•
Inserción de un registro.
La mayor parte de las operaciones de recuperación, y actualización, implican la realización de una
localización, o búsqueda, de un registro concreto para luego actuar sobre él.
136
TEMA 8 – Estructuras básicas
8.4.2. Registros, campos y claves.
La unidad elemental que compone los archivos es el registro. Un registro se corresponde con
una ficha, o con una hoja de papel en un archivo manual. Cada registro de un archivo tiene, en
general, la misma estructura que los demás. Los registros no tienen siempre la misma longitud:
en un archivo de facturas, por ejemplo, el número de líneas de una factura (en un registro) no es
siempre el mismo. En los sistemas de almacenamiento masivo, hay que reservar un determinado
espacio para cada uno de los registros.
Los datos individuales ocupan campos dentro de los registros. Un campo puede tener una
longitud fija o variable. El término longitud de campo hace referencia al número máximo de
caracteres que puede albergar dicho campo. Los campos pueden ser de diferente tipo: numérico,
texto, moneda, fecha o código, donde los caracteres tienen un significado especial.
La forma más común de identificar un registro es eligiendo un campo dentro del registro.
Este campo se denomina clave del registro. La única restricción sobre las claves es que, cada
registro debe tener una clave diferente. Por esta y otras razones, se permite utilizar más de un
campo como clave para un registro. En este caso, los campos se denominan clave primaria, clave
secundaria, etc.
Por ejemplo, podríamos considerar la información contenida en una guía telefónica como un
archivo. Un registro serían los datos para una persona. En cada registro habrá cuatro campos:
apellidos, nombre, dirección y número de teléfono. La clave primaria estaría en el campo
dedicado a los apellidos y la clave secundaria en el campo del nombre. Ambas claves permiten
identificar a la persona de forma inequívoca, ya que los apellidos solos no son siempre suficiente.
8.4.3. Organización de archivos.
En los primeros tiempos de la informática la estructura de los archivos estaba determinada en
gran medida por los medios de almacenamiento disponibles. Hoy en día la situación se ha invertido.
La naturaleza de las aplicaciones determina la estructura de los archivos, que es la que define los
medios de almacenamiento que hay que utilizar. Las estructuras más comunes para los archivos son:
secuencial, directa e indexada.
8.4.3.1. Organización secuencial.
En esta organización los registros figuran almacenados contiguamente (uno a continuación
de otro), siguiendo la secuencia lógica del archivo. La secuencia en la que aparecen los registros
en el archivo, puede estar determinada por el valor de algún campo, o ser simplemente temporal.
Los archivos secuenciales pueden almacenarse en cintas o discos magnéticos.
8.4.3.2. Organización directa.
Un archivo con organización directa o aleatoria es un archivo escrito sobre un soporte
direccionable para el cual existe una transformación conocida que genera la dirección de cada
137
Apuntes de Informática
registro en el archivo a partir de una llave. El calificativo aleatorio se debe a que normalmente
no existe ninguna vinculación aparente entre el orden lógico de los registros y su orden físico.
El problema fundamental de esta organización es la elección de la transformación, o método
de direccionamiento, que se ha de usar. En algunos casos, pueden aparecer las siguientes
situaciones no deseadas:
-
Direcciones que no corresponden a ninguna llave (zonas de disco sin utilizar).
Direcciones que corresponden a más de una llave.
Hay tres métodos fundamentales de direccionamiento para los archivos de organización
directa:
•
Directo. Si se utiliza como dirección la propia llave.
•
Asociado. A cada llave se le asocia una dirección mediante una tabla.
•
Calculado o por transformación de llave. La dirección se obtiene realizando
operaciones y transformaciones con la llave.
Los archivos aleatorios son los más apropiados para las aplicaciones en las que se necesita un
acceso rápido a los registros.
8.4.3.3. Organización secuencial indexada.
Los archivos secuenciales indexados son, actualmente, el tipo de archivos en uso más común.
Se trata de archivos secuenciales que disponen de un índice. Este índice es un conjunto de datos
que permite asociar la clave de un registro con su posición física en el disco. Es muy similar al
índice de un libro que relaciona palabras y párrafos con números de página. El índice se guarda
generalmente al principio del archivo, o, más comúnmente, en un archivo aparte. Si se utiliza
más de un nivel de indexado, las distintas partes del índice pueden guardarse a lo largo del
archivo.
Como estos archivos necesitan que los datos se localicen mediante su dirección, es necesario que
se almacenen en disco magnético. La técnica de indexado más simple hace referencia a la estructuras
de los paquetes de discos magnéticos. Esta técnica de denomina indexado por cilindro-superficie-ysector. Para cada paquete de discos del archivo existe un índice de cilindro. Una vez que se ha
seleccionado el cilindro, se utiliza un índice de superficie, y elegida la superficie, se emplea un índice
de sector. Una vez determinado el sector se puede acceder al registro deseado, copiando el sector en la
memoria principal. De todo esto puede deducirse que, para localizar un registro es necesario acceder
cuatro veces al disco, una vez para determinar cada índice y una vez más, para obtener el sector con
los datos.
Una ventaja de este tipo de archivos es la facilidad para dejar espacio entre los sectores,
superficies o cilindros con el fin de insertar nuevos registros. Esto permite que los archivos crezcan
sin necesidad de copiarlos a otro disco y reindexarlos con frecuencia.
138
TEMA 8 – Estructuras básicas
8.5. Utilización de las estructuras en los lenguajes de programación.
Las estructuras de datos que hemos visto, se han presentado en términos generales. Vistas de
este modo suelen denominarse estructuras de datos abstractas, con sus propiedades esenciales
definidas de forma completamente independiente de cada computador particular. Esto es
necesario para mantener la simplicidad de estas estructuras y para investigar más a fondo sus
propiedades.
Se plantean, pues, una serie de problemas cuando se representa cualquiera de estas
estructuras en un computador. En la mayoría de los casos, el método de representarla interfiere
con las propiedades de las mismas. Parte de la limpieza y simplicidad de la estructura abstracta
se pierde. El problema más común que se presenta es que los computadores tienen una capacidad
de memoria limitada. Todas las estructuras dinámicas que se han expuesto carecen de límites en
lo que se refiere al volumen que pueden alcanzar. En la práctica hay que imponer un límite a su
tamaño y deben realizarse comprobaciones cada vez que se añade un elemento.
139
Descargar