Ya sabes qué es una estructura de datos y por qué elegir bien importa. El siguiente paso natural es conocer el catálogo: ¿qué estructuras existen y cómo se clasifican? Esta lección es el mapa del curso: presentaremos las grandes familias de estructuras (lineales y no lineales, estáticas y dinámicas, homogéneas y heterogéneas), veremos qué papel jugará cada una en TaskFlow y repasaremos las estructuras que Python trae de serie, que serán nuestro punto de partida. No profundizaremos en ninguna —cada una tiene su propio módulo—, pero al terminar sabrás situar cualquier estructura en el mapa y entenderás el itinerario que seguiremos.
Contenido
- Clasificación 1: lineales vs no lineales
- Clasificación 2: estáticas vs dinámicas
- Clasificación 3: homogéneas vs heterogéneas
- El catálogo del curso y su papel en TaskFlow
- Las estructuras nativas de Python: nuestro punto de partida
Clasificación 1: lineales vs no lineales
La primera pregunta que puedes hacerle a cualquier estructura es: ¿cómo se relacionan sus elementos entre sí?
- En una estructura lineal, los elementos forman una secuencia: cada elemento tiene (como mucho) un anterior y un siguiente. Es la relación "uno detrás de otro".
- En una estructura no lineal, un elemento puede relacionarse con varios a la vez: jerarquías (un padre con varios hijos) o redes (conexiones arbitrarias entre nodos).
graph TB
subgraph Lineal
A1[Tarea 1] --> A2[Tarea 2] --> A3[Tarea 3] --> A4[Tarea 4]
end
subgraph No lineal: jerarquía
B1[Trabajo] --> B2[Cliente A]
B1 --> B3[Cliente B]
B2 --> B4[Facturas]
B2 --> B5[Reuniones]
end
subgraph No lineal: red
C1[Tarea A] --> C2[Tarea B]
C1 --> C3[Tarea C]
C2 --> C4[Tarea D]
C3 --> C4
end
En TaskFlow aparecen los tres patrones de forma natural:
- El tablero de tareas es lineal: las tareas van en orden, una tras otra.
- Las categorías son jerárquicas: "Trabajo" contiene "Cliente A", que contiene "Facturas".
- Las dependencias son una red: la tarea D depende de B y de C, que a su vez dependen de A.
Son lineales las listas, las pilas y las colas (módulos 2 a 4). Son no lineales los árboles (jerarquías, módulo 6) y los grafos (redes, módulo 7). Las tablas hash (módulo 5) son un caso aparte: sus elementos no mantienen ninguna relación de orden entre sí —ni secuencia ni jerarquía—; lo que las define es la asociación directa entre cada clave y su valor.
La clasificación importa porque determina cómo se recorre la estructura: una secuencia se recorre de principio a fin; una jerarquía o una red exigen estrategias de recorrido más elaboradas (las veremos en sus módulos).
Clasificación 2: estáticas vs dinámicas
La segunda pregunta: ¿puede cambiar el tamaño de la estructura durante la ejecución?
- Una estructura estática tiene un tamaño fijo, decidido al crearla. Ocupa un bloque de memoria de tamaño conocido y no crece ni mengua.
- Una estructura dinámica crece y se encoge según se insertan o eliminan elementos, adaptando su uso de memoria en tiempo de ejecución.
| Aspecto | Estática | Dinámica |
|---|---|---|
| Tamaño | Fijado al crearla | Cambia durante la ejecución |
| Memoria | Reservada de golpe, contigua | Se pide y libera sobre la marcha |
| Ventaja principal | Simplicidad y acceso muy rápido | Flexibilidad: no hay que predecir el tamaño |
| Riesgo típico | Quedarse corta o desperdiciar espacio | Coste extra de gestión de memoria |
| Ejemplo clásico | Array de tamaño fijo (C, Java) | Lista enlazada, list de Python |
El ejemplo canónico de estructura estática es el array de tamaño fijo, habitual en lenguajes como C o Java: pides sitio para exactamente 100 elementos y eso tienes. En Python casi todo lo que usarás es dinámico —una list crece sin que te preocupes de nada—, pero la distinción sigue siendo crucial por dos motivos:
- Las estructuras dinámicas de Python están construidas sobre mecanismos estáticos por debajo, y ese "por debajo" explica sus costes (lo veremos en la lección 01-05 con los arrays y la memoria).
- En cuanto salgas de Python (bases de datos, sistemas embebidos, otros lenguajes), los tamaños fijos vuelven a aparecer.
Para TaskFlow: el número de tareas es imprevisible y cambia constantemente, así que necesitaremos estructuras dinámicas casi siempre. En cambio, algo como los tres estados posibles de una tarea (pendiente, en curso, hecha) es un conjunto fijo que jamás crece: una estructura estática e inmutable (una tupla, como veremos abajo) lo representa mejor.
Clasificación 3: homogéneas vs heterogéneas
Tercera pregunta: ¿todos los elementos son del mismo tipo?
- Una estructura homogénea solo admite elementos de un mismo tipo: todos enteros, todos cadenas...
- Una estructura heterogénea mezcla tipos: un entero junto a una cadena junto a un objeto.
# Homogénea: ids de tareas, todos enteros
ids_pendientes = [4, 8, 15, 16, 23]
# Heterogénea: una tarea con campos de distintos tipos
tarea = {
"id": 42, # entero
"titulo": "Migrar servidor", # cadena
"prioridad": "alta", # cadena
"completada": False, # booleano
"etiquetas": ["infra", "urgente"], # ¡otra estructura dentro!
}En lenguajes con tipado estricto (C, Java), los arrays son homogéneos por obligación. Python es flexible: una list admite cualquier mezcla. Pero que puedas mezclar no significa que debas: en la práctica profesional, las colecciones suelen mantenerse homogéneas ("una lista de tareas", "un conjunto de ids") y la heterogeneidad se reserva para representar registros con campos con nombre, como el diccionario tarea del ejemplo. Esta disciplina hace el código predecible: si sabes que ids_pendientes solo contiene enteros, puedes operar con confianza sobre cualquiera de sus elementos.
Fíjate también en la última línea del ejemplo: "etiquetas" contiene una lista dentro del diccionario. Las estructuras se componen unas dentro de otras, y las aplicaciones reales —TaskFlow incluida— son siempre composiciones: una lista de diccionarios, un diccionario de listas, un árbol cuyos nodos contienen colas...
El catálogo del curso y su papel en TaskFlow
Con las tres clasificaciones en la mano, ya podemos presentar el catálogo completo de estructuras que estudiaremos, cada una con la necesidad de TaskFlow que resolverá:
| Estructura | Familia | Idea en una frase | Uso en TaskFlow | Módulo |
|---|---|---|---|---|
| Lista | Lineal, dinámica | Secuencia de elementos en orden | El tablero de tareas | 2 |
| Pila | Lineal, dinámica | El último en entrar es el primero en salir (LIFO) | El "deshacer" de acciones | 3 |
| Cola | Lineal, dinámica | El primero en entrar es el primero en salir (FIFO) | El procesado de notificaciones | 4 |
| Tabla hash | Asociativa, dinámica | Cada clave lleva directamente a su valor | Búsqueda instantánea por id | 5 |
| Árbol | No lineal (jerarquía), dinámica | Nodos padre con nodos hijo | Categorías y subcategorías | 6 |
| Grafo | No lineal (red), dinámica | Nodos conectados entre sí libremente | Dependencias entre tareas | 7 |
Dos observaciones sobre la tabla:
- Los términos LIFO (Last In, First Out) y FIFO (First In, First Out) son la única "jerga" nueva: descríbelos mentalmente como la pila de platos y la cola del supermercado de la lección 01-01, y tendrás el 90 % de la intuición.
- El orden de los módulos no es casual: es de lo más simple a lo más rico. Las pilas y colas se construyen a partir de ideas de las listas; los árboles generalizan la idea de "elemento que apunta a otros"; los grafos generalizan los árboles. Cada módulo se apoya en el anterior, igual que TaskFlow crecerá pieza a pieza.
El recorrido completo, visto como itinerario:
graph LR
L[Listas<br/>M2] --> P[Pilas<br/>M3] --> C[Colas<br/>M4] --> H[Tablas hash<br/>M5] --> A[Árboles<br/>M6] --> G[Grafos<br/>M7]
Recuerda que esta lección es solo el mapa: la definición precisa de cada estructura, sus operaciones, implementaciones y costes se desarrollan en su módulo correspondiente.
Las estructuras nativas de Python: nuestro punto de partida
Python incorpora de serie cuatro estructuras de datos que usaremos constantemente, tanto por sí mismas como para construir las estructuras del catálogo. Conviene tener claro el papel de cada una:
| Estructura | Sintaxis | ¿Ordenada? | ¿Mutable? | ¿Duplicados? | Uso típico |
|---|---|---|---|---|---|
list |
[1, 2, 3] |
Sí (por posición) | Sí | Sí | Secuencias que cambian |
tuple |
(1, 2, 3) |
Sí (por posición) | No | Sí | Registros fijos, constantes |
dict |
{"a": 1} |
Por inserción | Sí | Claves no | Asociaciones clave → valor |
set |
{1, 2, 3} |
No | Sí | No | Pertenencia y unicidad |
("Mutable" significa que puede modificarse después de creada; "ordenada", que sus elementos mantienen un orden definido.)
Veámoslas en acción con datos de TaskFlow:
# list: el borrador del tablero — orden y cambios constantes
tablero = ["Diseñar logo", "Escribir informe", "Enviar factura"]
tablero.append("Llamar al cliente") # crece dinámicamente
# tuple: los estados posibles — un conjunto FIJO que nadie debe tocar
ESTADOS = ("pendiente", "en curso", "hecha")
# ESTADOS.append("otra") -> AttributeError: las tuplas no cambian
# dict: una tarea como registro heterogéneo con campos con nombre
tarea = {"id": 7, "titulo": "Enviar factura", "estado": "pendiente"}
print(tarea["titulo"]) # acceso por clave, no por posición
# set: etiquetas únicas usadas en el proyecto — sin duplicados
etiquetas = {"urgente", "cliente", "urgente"}
print(etiquetas) # {'urgente', 'cliente'} — el duplicado desaparecePuntos que conviene destacar del ejemplo:
tablero.append(...)muestra la naturaleza dinámica delist: crece sin declarar tamaño.ESTADOScomo tupla es la elección estática e inmutable correcta para datos que no deben cambiar; si alguien intenta modificarla, Python lanza un error, protegiendo el programa. La convención de escribirla en mayúsculas señala "esto es una constante".- El
seteliminó el duplicado"urgente"automáticamente: la unicidad es parte de su contrato. - Estas cuatro estructuras son, en términos de la lección 01-01, implementaciones muy pulidas de ciertos TDA:
listde una secuencia dinámica,dictde una tabla asociativa,setde un conjunto matemático. En los próximos módulos las usaremos tanto directamente como de "material de construcción" para implementar pilas, colas, árboles y grafos.
¿Y las estructuras que Python no trae de serie (listas enlazadas, árboles, grafos)? Las construiremos nosotros con clases, exactamente como hicimos con PilaConLista en la lección 01-01. Ahí está buena parte del valor del curso: no solo usar estructuras, sino saber fabricarlas.
Errores Comunes y Consejos
- Usar
listpara todo. Es el vicio número uno del principiante en Python: la lista es tan cómoda que se convierte en martillo universal. Antes de escribir[], pregúntate: ¿necesito orden? (si no, quizáset), ¿accedo por nombre? (quizádict), ¿los datos son fijos? (quizátuple). - Confundir la sintaxis de
dictyset. Ambos usan llaves:{"a": 1}es un diccionario (tieneclave: valor),{"a", "b"}es un conjunto (solo valores). Y ojo:{}a secas crea un diccionario vacío; para un conjunto vacío hay que escribirset(). - Creer que las clasificaciones son compartimentos rígidos. Son ejes de análisis, no cajones excluyentes: una misma estructura puede describirse desde los tres ejes a la vez (una
listde Python es lineal, dinámica y potencialmente heterogénea), y las tablas hash no encajan del todo en el eje lineal/no lineal. - Consejo: cuando encuentres una estructura nueva en cualquier lenguaje o librería (un
deque, unDataFrame, unTreeMapde Java...), sitúala en los tres ejes de esta lección y busca a qué TDA responde. Es la forma más rápida de "leer" una estructura desconocida.
Ejercicios
Ejercicio 1: clasificar estructuras
Clasifica cada escenario según los ejes vistos (lineal/no lineal; y donde tenga sentido, estática/dinámica y homogénea/heterogénea):
- Los meses del año en una aplicación de calendario.
- El organigrama de una empresa.
- La cola de impresión de una oficina.
- Las conexiones de amistad de una red social.
Ejercicio 2: elegir la estructura nativa
Para cada necesidad de TaskFlow, elige la estructura nativa de Python más adecuada (list, tuple, dict o set) y justifica en una frase:
- Los días de la semana en los que se pueden programar recordatorios (lunes a domingo, fijos).
- Los ids de las tareas que el usuario ha marcado como favoritas (sin repetidos, sin orden relevante).
- La correspondencia entre cada usuario y su lista de proyectos.
- El historial de títulos de tareas consultadas, en orden, con posibles repeticiones.
Ejercicio 3: componer estructuras
Escribe en Python la representación de un mini-tablero de TaskFlow con estos requisitos: debe haber tres columnas fijas de estado (pendiente, en curso, hecha); cada columna contiene sus tareas en orden; cada tarea tiene id, titulo y un conjunto de etiquetas sin duplicados. Crea el tablero con al menos dos tareas y escribe una línea de código que añada una etiqueta a una tarea existente. Indica qué estructura nativa usaste para cada nivel y por qué.
Soluciones
Solución 1:
- Meses del año: lineal (secuencia con orden), estática (siempre son 12) y homogénea (todos cadenas). En Python, una tupla sería lo natural.
- Organigrama: no lineal, jerárquico (cada persona tiene un responsable y puede tener varios subordinados): la forma de un árbol. Dinámica (la plantilla cambia).
- Cola de impresión: lineal y dinámica; el orden de llegada es la relación esencial (FIFO). Homogénea (todo son trabajos de impresión).
- Amistades: no lineal, en red (cada persona se conecta con muchas otras sin jerarquía): la forma de un grafo. Dinámica.
Solución 2:
tuple: colección fija y ordenada que no debe modificarse:DIAS = ("lunes", ..., "domingo").set: unicidad garantizada y pertenencia rápida; el orden no importa:favoritas = {4, 8, 15}.dict: asociación clave → valor, con el usuario como clave y su lista de proyectos como valor:{"ana": ["web", "app"]}(fíjate: undictque contienelist, composición de estructuras).list: secuencia ordenada, dinámica y con duplicados permitidos: exactamente el contrato de la lista.
Solución 3:
tablero = {
"pendiente": [
{"id": 1, "titulo": "Diseñar logo", "etiquetas": {"diseño", "cliente"}},
{"id": 2, "titulo": "Enviar factura", "etiquetas": {"admin"}},
],
"en curso": [],
"hecha": [],
}
# Añadir una etiqueta a la tarea con id 1 (primera de "pendiente"):
tablero["pendiente"][0]["etiquetas"].add("urgente")Justificación por niveles: un dict para las columnas (acceso por nombre de estado); una list por columna (las tareas mantienen un orden y la colección crece y mengua); un dict por tarea (registro heterogéneo con campos con nombre); un set para las etiquetas (unicidad automática). Cuatro estructuras nativas componiéndose para modelar un dominio real. Nota: las tres claves de estado son fijas, pero un dict es la opción práctica para acceder por nombre; la inmutabilidad de "solo hay tres estados" la reforzaremos con otras técnicas más adelante.
Conclusión
Ya tienes el mapa completo: las estructuras se clasifican según cómo se relacionan sus elementos (lineales como listas, pilas y colas; no lineales como árboles y grafos; asociativas como las tablas hash), según si su tamaño es fijo o variable (estáticas vs dinámicas) y según si mezclan tipos (homogéneas vs heterogéneas). Sabes qué papel jugará cada una en TaskFlow y cuentas con las cuatro estructuras nativas de Python —list, tuple, dict, set— como material de partida y de construcción.
Pero al mapa le falta una dimensión: los números. Dijimos que la tabla hash busca "al instante" y que la lista "recorre todo"... ¿cómo se expresa eso con precisión, de forma que podamos comparar estructuras rigurosamente? Ese es el propósito de la próxima lección: la notación Big O, el lenguaje universal para hablar de eficiencia que usaremos durante todo el resto del curso.
Curso de Estructuras de Datos
Módulo 1: Introducción a las Estructuras de Datos
- ¿Qué son las Estructuras de Datos?
- Importancia de las Estructuras de Datos en la Programación
- Tipos de Estructuras de Datos
- Complejidad Algorítmica y Notación Big O
- Arrays y Memoria: la Base de las Estructuras de Datos
Módulo 2: Listas
- Introducción a las Listas
- Listas Enlazadas
- Listas Doblemente Enlazadas
- Listas Circulares
- Ejercicios con Listas
Módulo 3: Pilas
- Introducción a las Pilas
- Operaciones Básicas con Pilas
- Implementación de Pilas
- Aplicaciones de las Pilas
- Ejercicios con Pilas
Módulo 4: Colas
- Introducción a las Colas
- Operaciones Básicas con Colas
- Colas Circulares
- Colas de Prioridad
- Colas Dobles (Deques)
- Ejercicios con Colas
Módulo 5: Tablas Hash y Diccionarios
- Introducción a las Tablas Hash
- Funciones Hash y Resolución de Colisiones
- Diccionarios y Conjuntos en la Práctica
- Ejercicios con Tablas Hash
Módulo 6: Árboles
- Introducción a los Árboles
- Árboles Binarios
- Recorridos de Árboles
- Árboles Binarios de Búsqueda
- Árboles AVL
- Árboles B
- Montículos (Heaps)
- Ejercicios con Árboles
Módulo 7: Grafos
- Introducción a los Grafos
- Representación de Grafos
- Algoritmos de Búsqueda en Grafos
- Algoritmos de Caminos Mínimos
- Árboles de Expansión Mínima
- Aplicaciones de los Grafos
- Ejercicios con Grafos
