Las estructuras de datos son formas organizadas de almacenar y gestionar la información en la memoria de una computadora para que pueda ser utilizada de manera eficiente. No se trata solo de guardar números o letras, sino de definir cómo se relacionan entre sí esos elementos y cómo se accede a ellos mediante operaciones específicas. Esta organización determina directamente el rendimiento de un programa, influyendo en la velocidad de ejecución y en la cantidad de memoria necesaria.
En la ciencia de la computación, elegir la estructura adecuada es tan crucial como el algoritmo que la procesa. Una mala elección puede hacer que una aplicación funcione casi al instante o que tarde horas en devolver un resultado, incluso procesando los mismos datos. Desde listas simples hasta árboles complejos, estas herramientas son los cimientos sobre los que se construyen los lenguajes de programación y los sistemas operativos modernos.
Definición y concepto
Las estructuras de datos son mecanismos fundamentales en la informática para organizar, almacenar y gestionar conjuntos de información. Su objetivo principal es permitir que los datos sean accedidos y modificados de manera eficiente. Sin una organización adecuada, los datos se comportan como un archivo desordenado donde encontrar un elemento específico requiere revisar casi todo el conjunto.
Datos en bruto frente a datos estructurados
Es crucial distinguir entre el dato en sí mismo y la forma en que se organiza. Un dato en bruto es una unidad de información aislada. Por ejemplo, el número entero 42 o la cadena de caracteres "Hola" son datos básicos. Por sí solos, su utilidad es limitada porque carecen de contexto relacional.
Los datos estructurados, en cambio, implican una relación definida entre múltiples elementos. Cuando agrupamos esos números en una lista ordenada o los colocamos en una tabla con filas y columnas, estamos creando una estructura. Esta organización permite predecir dónde está un dato y cómo se relaciona con sus vecinos. La diferencia no está en el contenido, sino en la arquitectura que lo sostiene.
La relación simbiótica con los algoritmos
En la ciencia de la computación, las estructuras de datos y los algoritmos son inseparables. No se puede entender uno sin el otro. Los algoritmos definen el proceso lógico, el "cómo" se resuelve un problema paso a paso. Las estructuras de datos definen el "dónde" se almacena la información y cómo se accede a ella.
Debate actual: Muchos estudiantes principiantes creen que el algoritmo es lo más importante porque es la lógica visible. Sin embargo, un algoritmo brillante aplicado a una mala estructura de datos puede resultar más lento que un algoritmo simple sobre una estructura óptima. La elección de la estructura a menudo determina el techo de rendimiento del software.
Esta interdependencia se resume frecuentemente con la fórmula conceptual:
Datos+Algoritmos=ProgramaUn algoritmo de búsqueda lineal, por ejemplo, recorre los elementos uno por uno. Si aplicamos este algoritmo a una lista vinculada, el rendimiento será aceptable. Si lo aplicamos a un árbol binario de búsqueda sin aprovechar su ordenación, estamos desperdiciando la potencia de la estructura. La estructura proporciona el escenario; el algoritmo es la actuación.
Impacto en el rendimiento del software
La elección correcta de la estructura de datos afecta directamente dos recursos críticos: el tiempo de ejecución y el uso de memoria. Ningún recurso es infinito en un sistema computacional.
El tiempo de ejecución se mide a menudo usando la notación asintótica, como la complejidad temporal. Una estructura puede reducir el tiempo de búsqueda de todos los elementos (complejidad lineal, O(n)) a solo unos pocos pasos (complejidad logarítmica, O(logn)). Esta diferencia es exponencial cuando se manejan millones de registros.
La memoria es el otro factor. Algunas estructuras requieren poco espacio pero son lentas al acceder a los datos, como las listas vinculadas simples. Otras, como las tablas hash, pueden consumir mucha memoria adicional para lograr un acceso casi instantáneo. El programador debe equilibrar esta compensación según las necesidades específicas del problema.
Un ejemplo histórico ilustra esto: cuando los sistemas operativos comenzaron a manejar miles de archivos, pasar de una lista simple a un árbol de directorios redujo drásticamente el tiempo de carga del sistema. La consecuencia es directa. Una mala elección estructural puede hacer que una aplicación pase de responder en milisegundos a tardar segundos, lo que para el usuario final significa la diferencia entre fluidez y latencia perceptible.
Entender estas estructuras no es solo teoría; es la base para escribir software escalable. Sin ellas, el código funciona, pero rara vez es eficiente a gran escala.
Historia y evolución
El concepto de estructura de datos no nació con la computadora moderna, aunque su formalización académica es relativamente reciente. En los inicios de la computación, los datos eran entidades estáticas, a menudo ancladas a registros en la memoria principal. Sin embargo, la verdadera revolución llegó con la necesidad de organizar la información de manera dinámica, permitiendo que el tamaño y la forma de los datos cambiaran durante la ejecución del programa.
Niklaus Wirth, creador del lenguaje Pascal, sintetizó esta evolución en su influyente libro de 1976, Algoritmos + Estructuras de Datos = Programas. Wirth argumentaba que la eficiencia de un algoritmo dependía intrínsecamente de cómo se organizaban los datos subyacentes. Esta ecuación se convirtió en el lema central de la ingeniería de software durante décadas. La idea era simple pero poderosa: sin una estructura adecuada, incluso el mejor algoritmo se volvía ineficiente.
De los punteros a las colecciones genéricas
En la era de los punteros, representativa del lenguaje C, la gestión de la memoria era manual. Los programadores debían asignar y liberar memoria explícitamente, lo que ofrecía un control granular pero aumentaba la carga cognitiva y el riesgo de errores como las fugas de memoria. Las estructuras eran rígidas; una lista enlazada de enteros rara vez aceptaba un carácter sin modificar su definición.
Dato curioso: La famosa ecuación de Wirth se ha vuelto tan icónica que muchos lenguajes modernos intentan resolverla automáticamente mediante recolección de basura y tipos genéricos, ocultando la complejidad que Wirth puso sobre la mesa.
Con la llegada de lenguajes como Java, Python y JavaScript, las estructuras se volvieron genéricas. Las colecciones comenzaron a aceptar tipos de datos flexibles mediante parámetros de tipo o inferencia dinámica. Esto permitió reutilizar la misma estructura, como una lista o un diccionario, para almacenar casi cualquier cosa sin reescribir el código base. La abstracción aumentó, permitiendo a los desarrolladores centrarse más en la lógica del algoritmo que en la gestión de la memoria.
La era del Big Data y la computación distribuida
La aparición del Big Data obligó a las estructuras de datos a salir de la memoria de una sola máquina. Ya no bastaba con optimizar el acceso a un arreglo; era necesario considerar cómo se distribuyen los datos entre cientos de nodos en una red. Esto dio lugar a estructuras especializadas diseñadas para la concurrencia y la escalabilidad horizontal.
Estructuras como los árboles B+ se volvieron estándar en bases de datos relacionales para optimizar el acceso a disco, mientras que las tablas hash distribuidas se convirtieron en la columna vertebral de sistemas como Cassandra o DynamoDB. En la computación distribuida, la coherencia de los datos se convirtió en un desafío tan grande como la propia organización de los mismos. La eficiencia ya no se medía solo en operaciones por segundo, sino en la latencia de red y la tolerancia a fallos.
La evolución de las estructuras de datos refleja el cambio de enfoque en la informática: de la optimización microscópica de la memoria a la gestión macroscópica de la información a escala global. Comprender esta historia es esencial para elegir la herramienta adecuada en un entorno tecnológico en constante expansión.
¿Qué tipos de estructuras de datos existen?
Clasificación general
Las estructuras de datos se clasifican según cómo organizan la información en memoria. La distinción principal radica en su tamaño: las estáticas tienen un tamaño fijo definido al crearlas, como los vectores clásicos; las dinámicas crecen o se encogen según la necesidad, ajustando el espacio en tiempo de ejecución. Otra división fundamental es la forma: las lineales organizan los elementos en una secuencia sucesiva, mientras que las no lineales establecen relaciones jerárquicas o de red entre ellos.
Estructuras lineales fundamentales
Los arrays (o vectores) son bloques contiguos de memoria donde cada elemento se accede mediante un índice numérico. Su fortaleza es la velocidad de acceso directo, pero insertar elementos en el medio requiere desplazar todos los siguientes. Las listas enlazadas resuelven esta rigidez: cada elemento (nodo) contiene el dato y una referencia al siguiente nodo. Esto permite inserciones rápidas, aunque perder la ventaja del acceso aleatorio.
Las pilas siguen el principio LIFO (Last In, First Out): el último elemento en entrar es el primero en salir, similar a una pila de platos. Se usan intensivamente en el control de flujo de funciones. Las colas operan al revés con el principio FIFO (First In, First Out): el primero en llegar es el primero en salir, ideal para gestionar procesos en espera.
Dato curioso: La pila es tan fundamental que la memoria principal de tu computadora usa una "pila de llamadas" para saber qué función ejecutar cuando termina la actual. Sin ella, el programa se perdería en el código.
Estructuras no lineales
Los árboles organizan datos jerárquicamente. Los árboles binarios de búsqueda (BST) mantienen el orden: los valores menores van a la izquierda y los mayores a la derecha, facilitando búsquedas rápidas. Los heaps (montículos) son árboles casi completos optimizados para acceder al valor máximo o mínimo rápidamente, esenciales en algoritmos de prioridad.
Los grafos son la estructura más flexible, compuesta por nodos (vértices) conectados por aristas. Modelan redes sociales, rutas de transporte o la propia internet. No tienen un inicio ni un final fijos, lo que permite representar relaciones complejas donde cada elemento puede conectarse con casi cualquier otro.
Tablas Hash
Las tablas hash no ordenan los datos espacialmente, sino que usan una función matemática para calcular la posición de cada elemento. Esto permite acceder a los datos con una velocidad casi constante, independientemente del tamaño de la colección, aunque requieren resolver colisiones cuando dos datos caen en la misma posición.
Comparativa de complejidad
La eficiencia se mide usando la notación Big O, que describe cómo crece el tiempo de ejecución o el espacio usado a medida que aumenta la cantidad de datos (n). A continuación se presenta una comparación de las operaciones más comunes:
| Estructura | Acceso | Búsqueda | Inserción | Eliminación |
|---|---|---|---|---|
| Array | O(1) | O(n) | O(n) | O(n) |
| Lista Enlazada | O(n) | O(n) | O(1)* | O(1)* |
| Árbol Binario (BST) | O(log n)** | O(log n)** | O(log n)** | O(log n)** |
| Tabla Hash | N/A | O(1)*** | O(1)*** | O(1)*** |
*Si ya se conoce la posición del nodo. En el caso promedio si el árbol está balanceado. *En el caso promedio sin muchas colisiones.
La elección depende del problema. Si necesitas leer mucho y escribir poco, un Array es ideal. Si la prioridad es la velocidad de búsqueda en grandes volúmenes, las Tablas Hash suelen ser la reina. Ninguna estructura es perfecta para todo.
¿Cómo se mide la eficiencia de una estructura de datos?
Evaluar si una estructura de datos es eficiente no depende únicamente de qué tan rápido se ejecute en una máquina específica, sino de cómo crece su demanda de recursos a medida que aumenta la cantidad de datos. Para estandarizar esta medición, la ciencia de la computación utiliza la Notación Big O (Gran O). Esta notación describe el límite superior del crecimiento de una función, permitiendo a los desarrolladores predecir el comportamiento de un algoritmo sin depender de la velocidad del procesador o del tamaño exacto de la entrada.
Complejidad temporal y espacial
El análisis se divide en dos dimensiones principales: el tiempo y el espacio. La complejidad temporal mide cuántas operaciones básicas realiza un algoritmo en función del tamaño de la entrada, usualmente denotado como n. Por otro lado, la complejidad espacial evalúa cuánta memoria adicional requiere la estructura para almacenar los datos o para ejecutar el algoritmo.
No siempre existe una relación directa entre ambas. A veces, para ganar velocidad (tiempo), se sacrifica memoria (espacio). Un ejemplo clásico es la tabla hash, que puede ofrecer acceso casi instantáneo pero requiere más memoria que una lista simple. La elección depende de qué recurso sea más escaso en el contexto de la aplicación.
Casos de análisis: Mejor, promedio y peor
Al analizar una estructura, no basta con mirar un solo escenario. Se consideran tres casos para tener una visión completa:
- Mejor caso: El escenario más optimista, donde los datos están en la posición ideal. Suele ser menos útil porque rara vez se repite.
- Caso promedio: El rendimiento esperado estadísticamente sobre muchas ejecuciones con datos aleatorios.
- Peor caso: El escenario más desfavorable. Es crucial en sistemas de tiempo real (como la navegación aérea) donde un retraso excesivo puede ser crítico.
Dato curioso: En ingeniería de software, se suele priorizar el "Peor caso" porque garantiza que la aplicación no colapse bajo presión, incluso si el "Caso promedio" suele ser mucho más rápido.
Ejemplos prácticos: Arrays vs. Listas Enlazadas
La diferencia entre estructuras se vuelve evidente al comparar un Array (matriz) y una Lista Enlazada al buscar un elemento.
En un Array, los elementos están contiguos en la memoria. Si conoces el índice exacto, el acceso es directo y su complejidad es O(1) (tiempo constante). Sin embargo, si buscas un valor sin conocer su posición, debes revisar cada celda una por una, lo que resulta en una complejidad de O(n) (tiempo lineal).
En una Lista Enlazada, los elementos están dispersos y conectados por punteros. Para llegar al tercer elemento, debes pasar obligatoriamente por el primero y el segundo. Por lo tanto, buscar cualquier elemento específico siempre requiere recorrer la lista, manteniendo una complejidad de O(n) independientemente de si conoces el índice o no.
La importancia del análisis asintótico radica en la escalabilidad. Un algoritmo que parece rápido con 10 datos puede volverse lento con un millón. Entender estas diferencias permite seleccionar la herramienta correcta para que las aplicaciones sigan siendo eficientes a medida que los usuarios y los datos crecen.
Aplicaciones prácticas y ejemplos del mundo real
Las estructuras de datos no son abstracciones puras; son los cimientos invisibles de casi cada interacción digital. Elegir la estructura adecuada determina si una aplicación responde al instante o se congela. La eficiencia se mide a menudo en notación Big O, que describe cómo crece el tiempo de ejecución respecto al tamaño de los datos.
Gestión de estados y flujo: Pilas y Colas
El botón de "Atrás" en tu navegador web es un ejemplo clásico de una pila (stack). Funciona bajo el principio LIFO (Last In, First Out). Al visitar una página, se "empuja" a la cima; al retroceder, se "saca" la más reciente. El sistema de llamadas a funciones en programación, conocido como Call Stack, opera igual: la última función llamada es la primera en terminar y devolver el control.
Dato curioso: Si una función se llama a sí misma infinitamente sin terminar, se desborda la pila, provocando el famoso error "Stack Overflow", que dio nombre a la plataforma de preguntas para desarrolladores.
Las colas (queues) siguen el principio FIFO (First In, First Out). Son esenciales en la impresión de documentos: si envías tres hojas a la impresora, la primera en llegar es la primera en salir, a menos que haya interrupciones. Los sistemas operativos usan colas para gestionar las tareas de la CPU, asegurando que los procesos se ejecuten en orden de llegada o por prioridad.
Jerarquías y búsquedas: Árboles y Tablas Hash
Los árboles organizan datos jerárquicamente. El sistema de archivos de tu ordenador es un árbol: una raíz contiene carpetas, que a su vez contienen archivos o subcarpetas. En bases de datos, el Árbol B permite buscar registros en grandes discos duros con alta eficiencia, reduciendo el número de accesos físicos necesarios.
Las tablas hash ofrecen una velocidad de búsqueda media constante, denotada como O(1). Esto significa que, independientemente de si hay 10 o 10.000 elementos, el tiempo para encontrar uno específico apenas cambia. Los diccionarios en lenguajes como Python o JavaScript usan tablas hash internamente para mapear claves a valores rápidamente. También son la base de los sistemas de caché en servidores web.
Conexiones complejas: Grafos
Cuando los datos están interconectados de forma no lineal, entran en juego los grafos. Las redes sociales modelan usuarios como nodos y amistades como aristas. La recomendación de "amigos de amigos" surge al recorrer estos caminos. Google Maps utiliza grafos para calcular la ruta más corta entre dos puntos, aplicando algoritmos como el de Dijkstra, que evalúa el "peso" de cada calle (distancia o tráfico).
Entender estas aplicaciones permite a los desarrolladores elegir la herramienta correcta. Usar una lista enlazada cuando se necesita acceso aleatorio rápido puede ralentizar la aplicación. La elección correcta optimiza el uso de memoria y procesador.
¿Cómo elegir la estructura de datos adecuada?
No existe una estructura de datos universalmente perfecta. La elección óptima depende de cómo interactuará tu programa con la información. Un error común es seleccionar la estructura más obvia sin analizar las operaciones más frecuentes. Esto genera ineficiencias que escalan rápidamente cuando crece el conjunto de datos.
Factores críticos de decisión
El primer paso es evaluar el equilibrio entre lectura y escritura. Si los datos se leen constantemente pero rara vez cambian, una estructura estática como un Array suele ser eficiente. Por el contrario, si las inserciones y eliminaciones son frecuentes, una Lista Enlazada puede reducir la sobrecarga de desplazamiento de elementos. Analizar la proporción de operaciones define la arquitectura base.
El tamaño de los datos determina el medio de almacenamiento. Cuando la información cabe en la memoria RAM, el acceso es rápido y las estructuras complejas, como los árboles binarios, brillan por su flexibilidad. Si los datos superan la capacidad de la memoria y residen en el disco duro o en la base de datos, el costo de cada lectura aumenta. En ese escenario, estructuras como el Árbol B minimizan las accesos físicos al disco agrupando nodos. Ignorar esta distinción puede convertir una búsqueda rápida en un cuello de botella invisible.
La necesidad de ordenación también es determinante. Si el orden es crucial para la lógica del programa, un Árbol de Búsqueda Binaria mantiene los datos ordenados durante las inserciones. Si el orden es secundario, una Tabla Hash ofrece velocidad a cambio de perder la secuencia natural. No ordenar lo que no necesita estar ordenado ahorra ciclos de procesador.
Dato curioso: La elección entre una Tabla Hash y un Árbol Binario es clásica. Las tablas hash ofrecen acceso promedio en tiempo constante, pero en el peor de los casos pueden degradarse. Los árboles garantizan un orden predecible, pero requieren más memoria por nodo. Ninguna gana siempre.
El concepto de Trade-off
En ciencia de computación, casi todo es un compromiso o trade-off. Generalmente, se intercambia tiempo por espacio, o viceversa. Una estructura puede ser muy rápida en acceso, pero costosa en memoria. Otra puede ser compacta, pero lenta al buscar elementos. Entender este equilibrio evita la búsqueda de la perfección ilusoria.
La complejidad algorítmica se expresa a menudo con la notación de Orden de Magnitud. Por ejemplo, el acceso aleatorio en un Array suele tener una complejidad de tiempo constante:
T(n)=O(1)Esto significa que, independientemente del tamaño del array, acceder al quinto elemento toma el mismo tiempo que acceder al millonésimo. Sin embargo, insertar un elemento al inicio de ese mismo array requiere desplazar todos los demás, lo que resulta en una complejidad lineal:
T(n)=O(n)En cambio, una Lista Enlazada invierte esta dinámica. Insertar al inicio es rápido, pero acceder a un elemento por su posición requiere recorrer los anteriores uno por uno. La decisión depende de qué operación es el "cuello de botella" en tu aplicación específica.
Ejemplos prácticos de selección
Aplicar estos principios requiere mirar las necesidades concretas. Si necesitas acceso aleáneo rápido por índice, un Array es la opción estándar. Su contigüidad en memoria permite al procesador predecir los siguientes datos. Si las inserciones frecuentes ocurren al inicio y el orden de recorrido es más importante que el acceso directo, una Lista Enlazada reduce la fricción al evitar el desplazamiento de elementos. Para búsquedas rápidas por clave única, una Tabla Hash transforma la clave en un índice directo, logrando velocidad casi instantánea en la mayoría de los casos.
La clave no es memorizar cada estructura, sino entender qué pregunta le haces a tus datos. ¿Buscas por posición? ¿Por valor? ¿Por clave? La respuesta guía la elección. Un análisis superficial lleva a soluciones genéricas; un análisis profundo lleva a la eficiencia.
Ejercicios resueltos
La teoría cobra sentido cuando se aplica a problemas concretos. Los siguientes ejercicios muestran cómo elegir la estructura adecuada según el patrón de acceso a los datos.
Pila implementada con Array
Una pila sigue el principio LIFO (último en entrar, primero en salir). Usar un array dinámico permite acceder al elemento superior en tiempo constante. El método push añade al final; pop lo elimina del mismo lugar.
def push(pila, elemento):
pila.append(elemento)
def pop(pila):
if not pila:
return None
return pila.pop()
Al añadir o quitar del final del array, solo se modifica un puntero de tamaño. No hay desplazamientos masivos de memoria. La complejidad temporal es O(1) en el caso promedio. El espacio ocupa O(n), donde n es el número de elementos almacenados.
Recorrido en anchura (BFS) en un Grafo
El BFS explora vecinos cercanos antes de avanzar en profundidad. Requiere una Cola para mantener el orden de llegada. Este patrón es fundamental para encontrar la ruta más corta en grafos no ponderados.
def bfs(grafo, inicio):
cola = [inicio]
visitados = {inicio}
while cola:
nodo = cola.pop(0)
for vecino in grafo[nodo]:
if vecino not in visitados:
visitados.add(vecino)
cola.append(vecino)
Cada nodo se visita una vez y cada arista se revisa una vez. La complejidad temporal es O(V+E), con V vértices y E aristas. El espacio también escala con O(V) para almacenar los nodos en la cola y el conjunto de visitados.
Dato curioso: El algoritmo BFS fue desarrollado por Claude Shannon en 1947 para resolver laberintos en una máquina de discos magnéticos, mucho antes de que los grafos dominaran la informática.
Búsqueda binaria en Array ordenado
La búsqueda lineal revisa cada elemento, pero la búsqueda binaria aprovecha el orden. Divide el espacio de búsqueda a la mitad en cada paso, descartando la mitad que no contiene el objetivo.
def busqueda_binaria(arr, objetivo):
izq, der = 0, len(arr) - 1
while izq <= der:
medio = (izq + der) // 2
if arr[medio] == objetivo:
return medio
elif arr[medio] < objetivo:
izq = medio + 1
else:
der = medio - 1
return -1
En cada iteración, el tamaño del subarray se reduce a la mitad. Si el array tiene n elementos, después de k pasos quedan n/2k elementos. Cuando n/2k=1, se alcanza el caso base. Resolviendo para k, obtenemos k=log2(n). La complejidad temporal es O(logn). El espacio es O(1) si se usa la versión iterativa, ya que solo se necesitan tres variables de índice.
La eficiencia de la búsqueda binaria es dramática. Buscar en un millón de elementos toma como máximo 20 comparaciones, frente a un millón en la búsqueda lineal. Pero hay un matiz: el array debe estar ordenado, lo que añade un costo previo de O(nlogn) si se usa un algoritmo de ordenación eficiente como Merge Sort.
Preguntas frecuentes
¿Cuál es la diferencia entre una estructura de datos estática y una dinámica?
Las estructuras estáticas tienen un tamaño fijo definido al momento de la creación, como un arreglo tradicional. Las estructuras dinámicas pueden crecer o encogerse durante la ejecución del programa, adaptándose a la cantidad de datos, como ocurre con las listas enlazadas o los árboles binarios.
¿Qué es la complejidad temporal y por qué importa?
La complejidad temporal mide cuánto tiempo tarda una operación en completarse a medida que aumenta la cantidad de datos. Es fundamental porque permite predecir el rendimiento de un programa antes de ejecutarlo, usando notaciones como la Notación O Grande (Big O).
¿Cuándo debo usar una lista enlazada en lugar de un arreglo?
Se prefiere una lista enlazada cuando se necesitan inserciones o eliminaciones frecuentes en el medio de la secuencia sin desplazar todos los elementos. Los arreglos son mejores cuando se requiere acceso aleatorio rápido por índice y el tamaño de los datos es relativamente estable.
¿Qué es una tabla hash y para qué sirve?
Una tabla hash es una estructura que asocia claves con valores, permitiendo búsquedas extremadamente rápidas, a menudo en tiempo constante. Se utiliza ampliamente para implementar diccionarios, cachés y bases de datos donde la velocidad de recuperación es prioritaria.
¿Las estructuras de datos son lo mismo que los algoritmos?
No. Las estructuras de datos son la forma en que se organizan los datos (el "qué"), mientras que los algoritmos son los pasos lógicos para procesar esos datos (el "cómo"). Ambos trabajan juntos: un algoritmo eficiente depende de una estructura de datos adecuada.
Resumen
Las estructuras de datos son fundamentales para la eficiencia computacional, determinando cómo se almacena, accede y manipula la información en la memoria. Su selección depende del tipo de operaciones predominantes (búsqueda, inserción, ordenación) y de los recursos disponibles, equilibrando el uso de memoria contra la velocidad de procesamiento.
Comprender las diferencias entre estructuras lineales como arreglos y listas, y no lineales como árboles y grafos, permite a los desarrolladores optimizar el rendimiento de las aplicaciones. El análisis de la complejidad temporal y espacial mediante la Notación Big O proporciona una métrica objetiva para comparar estas estructuras y tomar decisiones de diseño informadas.