ESTRUCTURAS DE DATOS
Clase L
Una estructura de datos es una colección de datos que pueden ser caracterizados por su organización y las
operaciones que se definen en ella. Tienen una importancia fundamental en los sistemas de computadora. Los
tipos de datos se subdividen en dos grandes categorías:
† Datos simples o primitivos: significan que no están compuestos de otras estructuras de datos; los más
frecuentes y utilizados por casi todos los lenguajes son: enteros, reales y carácter (char), siendo los tipos
lógicos, subrango y enumerativos propios de lenguajes estructurados como pascal.
† Datos compuestos o estructurados: están construidos basados en tipos de datos primitivos; el ejemplo más
representativo es la cadena (string) de caracteres. Estos tipos de datos pueden ser organizados en dos
diferentes estructuras:
→ Estructuras de Datos Estáticos: son aquellas en las que el tamaño ocupado en memoria se define antes
de que el programa se ejecute y no puede modificarse dicho tamaño durante la ejecución del programa.
→ Estructuras de Datos Dinámicos: no tienen las limitaciones o restricciones en el tamaño de memoria
ocupada que son propias de las estructuras estáticas. Por excelencia son las listas —enlazadas, pilas,
colas—, árboles —binarios, árbol-b, búsqueda binaria— y grafos.
LOS ARRAYS UNIDIMENSIONALES: LOS VECTORES
Un array o arreglo (matriz o vector) es un conjunto finito y ordenado de elementos homogéneos. La propiedad
“ordenado” significa que el elemento primero, segundo, tercero, ..., enésimo de un array puede ser identificado.
El array unidimensional o vector (matriz de una dimensión) es el tipo más simple. Un vector de una dimensión
denominado notas que consta de n elementos se puede representar por la figura siguiente:
Los vectores se almacenan en la memoria central de la
computadora en un orden adyacente. Así, un vector de cincuenta
números denominado números se representa gráficamente por
cincuenta posiciones de memoria sucesivas.
MEMORIA
NUMEROS [1] DIRECCIÓN X
NUMEROS [2] DIRECCIÓN X+1
NUMEROS [3] DIRECCIÓN X+2
NUMEROS [50] DIRECCIÓN X+49
× Cada elemento de un vector se puede procesar como si fuese una variable simple al ocupar una posición de
memoria. Así, números [25] = 72 almacena el valor entero o real 72 en la posición 25.ª del vector números y la
instrucción de salida.
Console.writeln (numeros[25]) (Visualiza el valor almacenado en la posición 25.ª, en este caso 72.)
× Esta propiedad significa que cada elemento de un vector —y posteriormente una tabla o matriz— es accesible
directamente y es una de las ventajas más importantes de usar un vector: almacenar un conjunto de datos en
memoria principal.
LOS ARRAYS VARIAS DIMENSIONES
× Son representados mejor en forma de tabla o matriz con dos o más
subíndices.
Matriz de m x n dimensiones
Ejemplos típicos de tablas o matrices son: tablas de distancias kilométricas
entre ciudades, cuadros horarios de trenes o aviones, informes de ventas periódicas (mes/unidades vendidas o
bien mes/ventas totales), etc.
Se pueden definir tablas o matrices como arrays multidimensionales, cuyos elementos se pueden referenciar por
dos, tres o más subíndices. Los arrays no unidimensionales los dividiremos en dos grandes grupos: arrays
bidimensionales (2 dimensiones) y arrays multidimensionales (3 o más dimensiones).
ARRAYS BIDIMENSIONALES (TABLAS/MATRICES)
El array bidimensional se puede considerar como un vector de vectores. Es, por consiguiente, un conjunto de
elementos, todos del mismo tipo, en el cual el orden de los componentes es significativo y en el que se necesita
especificar dos subíndices para poder identificar cada elemento del array.
Un array bidimensional es un grupo de columnas, por ejemplo:
El diagrama representa una tabla o matriz de treinta elementos con 5
filas y 6 columnas. Como en un vector de treinta elementos, cada uno de
ellos tiene el mismo nombre. Los elementos de un array bidimensional se
referencian con dos subíndices: el primer subíndice se refiere a la fila y el
segundo subíndice se refiere a la columna.
× Un array bidimensional m, también denominado matriz (términos
matemáticos) o tabla (términos financieros), se considera que tiene
dos dimensiones (una dimensión por cada subíndice) y necesita un valor para cada subíndice para poder
identificar un elemento individual.
En notación estándar, normalmente el primer subíndice se refiere a la fila del array, mientras que el segundo
subíndice se refiere a la columna del array. Es decir, b[i, j] es el elemento de b que ocupa la iª fila y la jª
columna, como se indica en la figura.
Elemento b (i,j) de una matriz
B (m,n).
Clase M
ESTRUCTURAS DINÁMICAS (datos estructurados)
Es aquella en la que el tamaño ocupado en memoria puede modificarse durante la ejecución del programa.
Las variables que se crean y están disponibles durante la ejecución del programa se llaman variables continuas.
De esta manera se pueden adquirir posiciones adicionales de memoria a medida que se necesiten durante la
ejecución del programa y liberarlas cuando no se necesiten.
Estas variables se representan con un tipo de dato llamado puntero, los datos dinámicos se clasifican en lineales
(listas, pilas y colas) y no lineales (árboles y grafos)
Punteros
Es una variable que contiene la dirección de memoria de un dato o
de otra variable que contiene al dato en una lista. Esto quiere decir,
que el puntero apunta al espacio físico donde está el dato o la
variable.
Un puntero puede apuntar a un objeto de cualquier tipo como, por
ejemplo, a una estructura o una función. Los punteros se pueden
utilizar para referenciar y manipular estructuras de datos, para
referenciar bloques de memoria asignados dinámicamente y para
proveer el paso de argumentos por referencias en las llamadas a
funciones.
Listas
Es una colección de elementos organizados en secuencia que puede crecer y decrecer libremente y a cuyos
elementos individuales se puede acceder, insertar y eliminar en cualquier posición. Se clasifican en:
→ Listas Contiguas: Los elementos de la lista se almacenan normalmente en posiciones consecutivas de
memoria (almacenamiento secuencial), donde se define la constante longitud máxima, que determina el
tamaño de la mayor lista que se puede tener se implementan a través de arreglos, donde la inserción o
eliminación de un elemento excepto en la cabecera o al final de la lista necesitará una traslación de los
elementos de la lista.
→ Listas Enlazadas: Son mucho más flexibles que las listas contiguas, la inserción o borrado del elemento
enésimo no requiere el desplazamiento de los otros elementos de la lista.
Los elementos se almacenan en posiciones de memoria que no son continuas o adyacentes, por lo que cada
elemento necesita almacenar la posición o dirección del siguiente elemento de la lista.
Operación de Inserción en lista
enlazada.
Operación de Inserción en lista
contigua (arreglo).
Inserción al inicio
Inserción al final
Eliminación de un elemento
→ Listas Circulares: Corresponden al tipo de listas que poseen el campo siguiente del último elemento de la lista
apuntando al primero. De esta manera es posible acceder desde un elemento a cualquiera de los elementos
que le preceden. Se pueden producir lazos o bucles infinitos, para evitar esto siempre hay que contar con un
nodo que identifique el principio o el final de la lista.
→ Listas doblemente enlazadas: Corresponden al tipo de listas en las cuales el recorrido puede hacerse en
ambas direcciones. Además de utilizarse el puntero al siguiente se utiliza un puntero llamado anterior,
además de los siempre presentes punteros de inicio y fin.
Cada elemento tiene dos punteros y por consiguiente una lista enlazada ocupa más memoria que una lista
simplemente enlazada.
Pilas
O (stack) es un tipo especial de lista lineal en la que la inserción y borrado de nuevos elementos se realiza sólo por
un extremo, el cual es denominado cima o tope.
Dado que las operaciones de insertar y eliminar se realizan por un solo extremo (el superior), los elementos sólo
pueden eliminarse en orden inverso al que se insertan en la pila.
El último elemento que se introduce en la pila es el primero que se puede sacar, debido a esto a estas estructuras
se les denomina lifo (last-in, first-out).
Por ejemplo, se realiza una operación de inserción a la
estructura.
Colocando el elemento “a”, luego se procede a “apilar” el
elemento “b” y, seguidamente, se realiza lo mismo con el
elemento “c”.
Por último, se realiza una eliminación en la pila donde el
único elemento posible de eliminar, en principio, será el
elemento c, al ser el último en ingresar.
En principio la pila está vacía y el puntero de la pila o cima está en cero; al meter un elemento en la pila, se
incrementa el puntero en una unidad, al sacar un elemento de la pila, se decrementa el puntero en una unidad.
En una pila vacía no se pueden sacar datos (cima=0), si la pila se implementa con un array de tamaño “n”, se
puede llenar cuando cima=n, y el intento de introducir un elemento provocará un desbordamiento de pila.
Pilas de llamadas
Son utilizadas para solucionar una amplia variedad de tareas del tipo lifo. Se
utilizan en compiladores, sistemas operativos y en programas de aplicación.
Una pila de llamadas (en inglés call stack) es una estructura dinámica de
datos lifo, (una pila), que almacena la información sobre las subrutinas activas
de un programa de computadora.
Clase N
Colas
Es un tipo especial de lista lineal en la que la eliminación se realiza al principio de la lista y las inserciones se
realizan al final de la lista. En las colas el elemento que entró primero sale primero, y el que entra último sale
último, debido a esto a estas estructuras se les denomina fifo (first-in, first-out).
Las colas se pueden implementar con arreglos o punteros.
→ Inserción de un elemento: en el ejemplo un elemento es
agregado a la cola (izquierda) y como queda la cola luego de
que el nuevo elemento entra en la cola (derecha).
→ Eliminación de un elemento: en el ejemplo siguiente un
elemento es retirado de la cola (izquierda), posteriormente la
cola se reordena colocando al elemento 2 como el primer
candidato a salir (derecha).
Cola doble o bicola
Es un tipo especial de cola en la que las eliminaciones y las inserciones se pueden realizar en cualquiera de los dos
extremos de la lista.
→ Doble cola de entrada restringida: acepta inserciones sólo al final de la cola.
→ Doble cola de salida restringida: acepta eliminaciones sólo al frente de la cola.
Ejemplo:
Cola de procesos según orden de llegada. Estructura fifo para manejar los mensajes entre
cliente - servidor.
Colas de prioridad
Es una variante de la cola convencional y trabaja muy parecido a la anterior, sin embargo, esta tiene una
característica que cuando un nuevo elemento entra en la cola no siempre se coloca al final.
Este tipo de colas se utilizan para realizar un ordenamiento tipo fifo para elementos que necesitan manejarse a
través una determinada relevancia o prioridad y no de acuerdo al orden en que llegan las peticiones.
Tiene un mecanismo para determinar la prioridad de cada
elemento de la cola, cuando un elemento entra en la cola
lo primero que hace es ver que prioridad tiene y luego lo
inserta en la posición que le corresponde.
Como podemos apreciar un elemento con prioridad 1 es
colocado en la cola y es puesto casi hasta adelante, sin
embargo, al tener prioridad 1 no pudo llegar hasta el
principio ya que existía un elemento con mas prioridad
(prioridad 0) en la cola.
Una vez ordenados los elementos según su prioridad,
la extracción de los mismos se realiza de manera
convencional, como en una cola normal.
Otra de las cosas importantes cuando trabajamos con colas
(queue), ya sean de prioridad o no, es que existen
implementaciones con capacidad ilimitada o dinámica y
colas con capacidad limitada, por lo que, si un nuevo
elemento quiere entrar en la cola, será rechazado hasta
que por lo menos un elemento salga.