Estructuras de datos

Formas de organizar los datos de nuestra aplicación


Una vez que ya conocemos los tipos de datos elementales de Javascript, tenemos que comenzar a pensar más a lo grande. Estos tipos de datos son la naturaleza más pequeña que almacenamos en nuestro código. A medida que nuestra aplicación web va creciendo y haciéndose más grande, comenzaremos a crear estructuras cada vez más complejas.

Estas estructuras se denominan estructuras de datos y conociendo las más básicas suele ser suficiente. Sin embargo, cuantas más conozcamos y dominemos, mucho mejor. Estas estructuras de datos pueden ser de diversos tipos:

  • 1️⃣🟩 Estructuras elementales (primitivos): tipos de datos (post anterior)
  • 2️⃣🟩 Estructuras básicas: Arrays y Objetos
  • 3️⃣🟨 Estructuras básicas específicas: Set y Map
  • 4️⃣🟨 Estructuras lineales: Pilas, colas y listas enlazadas.
  • 5️⃣🟥 Estructuras no lineales: Grafos dirigidos y no dirigidos.
  • 6️⃣🟥 Estructuras avanzadas: Árbol binario, Árbol B y tablas hash.

Si estás en una fase inicial aprendiendo Javascript, es suficiente con centrarte en las dos estructuras básicas principales: y que he marcado en verde. Si ya tienes cierta experiencia y te resultan sencillas, echa un vistazo a las marcadas en amarillo. Si eres desarrollador avanzado, echa un vistazo también a las rojas.

Estructuras básicas

Como hemos mencionado, las estructuras elementales son simplemente tipos de datos individuales y muy básicos: Números, valores booleanos, cadenas de texto, números grandes y símbolos. Si no conoces estos tipos de datos, echa un vistazo al post anterior.

Pero dentro de las estructuras que solemos utilizar frecuentemente (que no entran dentro de los tipos primitivos), hay varias estructuras un poco más complejas:

🟩 Arrays

Los arrays son colecciones de elementos, colocados de forma secuencial, uno tras otro. Se utilizan para organizar grupos de datos, que tienen cierta relación entre sí, o que tienen cierto sentido que se coloquen juntos en una sola estructura y en un cierto orden.

Pueden ser de varios tipos:

Estructuras de datos básicas: Array o arreglos

  • 1️⃣ Arrays homogéneos: Colección de elementos del mismo tipo (todos números, por ejemplo).
  • 2️⃣ Arrays mixto: Colección de elementos de diferente tipo (diferentes).
  • 3️⃣ Arrays de arrays: Colección de elementos, donde sus elementos pueden ser también otros y que contienen a su vez más información.

Más adelante, hablaremos de las estructuras de tipo Array, sus métodos y temas relacionados.

🟩 Objetos

Los objetos en Javascript también son colecciones como los , pero tienen significativas diferencias. Son datos dobles: clave-valor, es decir, una estructura que contiene una colección de datos relacionados, donde cada dato tiene una clave y un valor.

Sus características son las siguientes:

Estructuras de datos básicas: Objetos o diccionarios

  • Al contrario que los , son estructuras que no están ordenadas. Simplemente se almacenan.
  • Al no estar ordenadas, no puedes recorrerlas (en principio, ya veremos matices más adelante).
  • Puedes acceder a sus claves, y así obtener el valor relacionado a esa clave.
  • Sólo pueden contener y como claves. No vale cualquier tipo.

Más adelante hablaremos de las estructuras de tipo Objeto, sus métodos y temas relacionados.

🟧 Set

Los Set o conjuntos, son colecciones de elementos similares a los Array, pero con una diferencia particular: no pueden contener elementos duplicados. Por ejemplo, si tenemos un set de números, el 5 solo puede insertarse una sola vez.

Esto lo hace una estructura de datos ideal si tienes esa restricción en tu caso de uso. Con un array, tendrías que estar controlándolo manualmente.

Estructuras de datos básicas: Set o conjuntos

  • Colección de elementos, muy similar a los
  • Importante: Los elementos no se pueden repetir si son iguales.

Más adelante, examinaremos los detalles de las estructuras de datos de tipo Set o conjuntos.

🟧 Map

Los Map o mapas, son estructuras muy similares a los objetos de Javascript, sin embargo, son un poco más potentes y eficientes. Es una estructura que permite almacenar pares clave-valor (como los objetos), pero con ciertas diferencias:

Estructuras de datos básicas: Map o mapas

  • Permite claves de cualquier tipo, no sólo y como los objetos.
  • Garantiza un orden de elementos insertados, al contrario que los objetos.
  • Es una estructura de datos más eficiente para búsquedas de datos.

Más adelante, profundizaremos en las estructuras de datos de tipo Map.

🟪 ArrayBuffer

Los ArrayBuffer (y tipos relacionados) son estructuras que permiten almacenar grandes volúmenes de información «cruda» en memoria. Esto los hace ideales para el trabajo con datos binarios como manipulación de imágenes o video o tareas donde necesitas manipular información de forma muy eficiente.

Estructuras de datos básicas 3

Además de ArrayBuffer, también tenemos tipos muy particulares y más específicos donde podemos determinar el tamaño que ocupan en memoria.

Tabla de tipos y tamaños
Bytes por elemento¿Con signo?UsoEjemplos
🟦 ArrayBuffer
Datos «raw»
N/ADatos binarios "crudos"Imágenes, archivos, buffers...
1️⃣ Int8Array
-128 a 127
Bytes con signoAudio PCM, valores negativos en red
1️⃣ Uint8Array
0 a 255
NoBytes sin signoImágenes, buffers binarios
1️⃣ Uint8ClampedArray
0 a 255
NoBytes sin signo, con clampingPíxeles en canvas
2️⃣ Int16Array
-32,768 a 32,767
Enteros de 16 bits con signoSeñales de audio, sensores
2️⃣ Uint16Array
0 a 65,535
NoEnteros de 16 bits sin signoColores RGB, formatos de archivo
4️⃣ Int32Array
-2,147,483,648 a 2,147,483,647
Enteros grandes con signoCálculos intensivos
4️⃣ Uint32Array
0 a 4,294,967,295
NoEnteros grandes sin signoWebGL, datos de alto rendimiento
4️⃣ Float32Array
±1.2×10⁻³⁸ a ±3.4×10³⁸
Coma flotante (simple)Gráficos 3D, física básica
8️⃣ Float64Array
±5.0×10⁻³²⁴ a ±1.8×10³⁰⁸
Coma flotante (doble)Finanzas, simulaciones científicas
8️⃣ BigInt64Array
-2⁶³ a 2⁶³-1
Enteros grandes con signoIdentificadores únicos, criptografía
8️⃣ BigUint64Array
0 a 2⁶⁴-1
NoEnteros grandes sin signoCriptografía, dir. de memoria

Estructuras lineales

Una vez conocemos las estructuras anteriores, probablemente necesitemos trabajar con estructuras más complejas o específicas. La mayoría de las estructuras que hemos visto hasta ahora son lineales, es decir, se pueden recorrer de forma secuencial.

Si seguimos dentro de estructuras lineales, podemos encontrarnos 4 tipos populares:

Estructuras de datos lineales

Vamos a verlo con ejemplos paso a paso:

🟪 Pila (Stack)

Las pilas son estructuras que se caracterizan en que sólo se pueden insertar elementos por un mismo extremo. Así pues, si insertas dos elementos (A, y luego B), tienes que sacar B antes para poder sacar A.

En Javascript, esto se puede hacer con una estructura usando los métodos .push() y .pop():

const array = [];

array.push("A");    // Mete A, Devuelve 1 (tamaño del array)
array.push("B");    // Mete B, Devuelve 2 (tamaño del array)
array.pop();        // Devuelve B
array.pop();        // Devuelve A
array.pop();        // Devuelve undefined

Casi siempre esto se suele denominar estructuras LIFO (Last input, first output): «El último que entra es el primero que sale».

🟪 Cola (Queue)

Las colas son estructuras que se caracterizan en que entran por un extremo y salen por el otro. Así pues, si insertas dos elementos (A, y luego B), primero sacar A y luego sacarás B.

En Javascript, esto se puede hacer con una estructura usando los métodos .push() y .shift():

const array = [];

array.push("A");    // Mete A, Devuelve 1 (tamaño del array)
array.push("B");    // Mete B, Devuelve 2 (tamaño del array)
array.shift();      // Devuelve A
array.shift();      // Devuelve B
array.shift();      // Devuelve undefined

Estas estructuras se denominan FIFO (First input, first output): «El primero que entra, es el primero que sale».

🟪 Cola doble (Deque)

Una modificación de las colas son las colas dobles. Estas son iguales que las colas simples, pero permiten tanto entrada como salida, por lo que es una estructura mucho más versátil:

En Javascript, se podría utilizar una estructura y combinar los métodos de las dos anteriores: .push(), .pop() y .shift(), usando también otro llamado .unshift().

const array = [];

array.push("A");    // Mete A, Devuelve 1 (tamaño del array)
array.push("B");    // Mete B, Devuelve 2 (tamaño del array)
array.push("C");    // Mete C, Devuelve 3 (tamaño del array)
array.pop();        // Devuelve C
array.shift();      // Devuelve A

array.unshift("Z"); // Mete Z, Queda ["Z", "B"], Devuelve 2 (tamaño del array)
array.push("X");    // Mete X, Queda ["Z", "B", "X"], Devuelve 3 (tamaño del array)

🟪 Listas enlazadas (Linked list)

Por último, tenemos las listas enlazadas. Estas estructuras pueden tener múltiples implementaciones y pueden ser mucho más complejas, pero básicamente se basan en que los datos enlazan al dato siguiente, de forma que teniendo acceso a uno de los datos, podemos acceder al siguiente:

  • Listas enlazadas: Acceso al siguiente elemento
  • Listas doblemente enlazadas: Acceso al siguiente y al anterior
  • Listas circulares: El último elemento enlaza al primer elemento
Estructuras de bajo nivel

Ten en cuenta que estas estructuras lineales no permiten acceder a elementos concretos directamente, como cuando hacemos un array[50]. Si necesitas ir al elemento 50, tendrás que recorrer 49 elementos antes. Esto hace que un sea más útil si necesitas acceder a elementos concretos.

Por otro lado, si no necesitas acceso a elementos concretos, pero vas a realizar muchas inserciones y/o eliminaciones, con una estructura de este tipo gastarías menos recursos. No obstante, aquí ya estamos hilando muy fino.

Estructuras no lineales

A medida que avanzamos en el desarrollo, nos iremos encontrando situaciones en las que necesitamos estructuras de datos no lineales, es decir, estructuras donde los datos no están organizados de forma secuencial, sino que tienen diferentes caminos y formas de relacionarse.

Esto suele ser así porque los datos están almacenados de una forma adecuada para que sea fácil y rápido encontrarlos.

Estructuras de datos no lineales

Este tipo de estructuras los datos se almacenan en elementos llamados nodos (las bolitas circulares) y se relacionan a través de líneas llamadas arcos o aristas.

Veamos que tipos existen:

🟥 Grafo dirigido

En los grafos dirigidos la principal características que es los nodos se enlazan en una dirección específica. Los nodos se relacionan a través de arcos que tienen una única dirección.

🟧 Grafo no dirigido

Por otro lado, los grafos no dirigidos tienen como principal característica que los nodos se enlazan mediante aristas, que tienen múltiples direcciones. De esta forma, nos podemos mover en cualquier dirección, no sólo una como en los anteriores.

Estas estructuras de datos son muy comunes en campos donde hay que relacionar grandes volúmenes de datos y necesitas que tengan un cierto orden y relación para facilitar ciertas cuestiones.

Estructuras avanzadas

Por último, tenemos estructuras avanzadas donde tienen características mucho más específicas y sirven para casos más avanzados de los que solemos hacer en un principio.

Por ejemplo, veamos tres casos bastante populares:

🟦 Árbol binario

Los árboles binarios (binary tree) son una estructura particular de las estructuras de tipo árbol. Estas estructuras se caracterizan en que son nodos con un valor numérico y que se dirigen hacia abajo. De cada nodo, pueden salir o colgar un número de nodos concreto. En el caso de los árboles binarios sólo pueden salir como máximo 2 nodos y como mínimo ninguno.

Estructuras de datos avanzadas: Árbol binario

La regla principal de un árbol binario es que el nodo hijo izquierdo debe tener un valor más pequeño que su padre, y el nodo hijo derecho debe tener un valor más grande que su padre. Esto lo hace una estructura intuitiva para recorrer.

🟪 Árbol B

Por otro lado, los árboles B (B tree) son estructuras de tipo árbol más avanzadas, donde cada nodo no está limitado a tener sólo dos hijos máximo, sino que puede tener múltiples hijos.

Estructuras de datos avanzadas: Árbol B

La particularidad de los árboles B es que deben estar balanceados para ser eficientes. Esto significa que la estructura debe tener un nivel de profundidad similar para todos sus nodos, y si insertamos nuevos elementos, el árbol B debe rebalancearse para mantener su efectividad de búsqueda.

Los árboles B (y algunas variantes como árboles B+) son las estructuras de base que utilizan muchas bases de datos, debido al buen rendimiento de búsqueda que tienen.

⬛ Tabla hash

Las tablas hash son estructuras que utilizan un algoritmo para transformar una cadena de texto en un número entero que se pueda utilizar como índice en la tabla. De esta forma, se pueden mapear claves a índices y permitir un acceso rápido y eficiente a la información.

Estructuras de datos avanzadas: Tablas hash

Las tablas hash se utilizan en una gran variedad de situaciones debido a su alta velocidad y lo eficiente y rápida que es la búsqueda de información.

¿Quién soy yo?

Soy Manz, vivo en Tenerife (España) y soy streamer partner en Twitch y profesor. Me apasiona el universo de la programación web, el diseño y desarrollo web y la tecnología en general. Aunque soy full-stack, mi pasión es el front-end, la terminal y crear cosas divertidas y locas.

Puedes encontrar más sobre mi en Manz.dev