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

  1. Clasificación 1: lineales vs no lineales
  2. Clasificación 2: estáticas vs dinámicas
  3. Clasificación 3: homogéneas vs heterogéneas
  4. El catálogo del curso y su papel en TaskFlow
  5. 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:

  1. 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).
  2. 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) Secuencias que cambian
tuple (1, 2, 3) Sí (por posición) No Registros fijos, constantes
dict {"a": 1} Por inserción Claves no Asociaciones clave → valor
set {1, 2, 3} No 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 desaparece

Puntos que conviene destacar del ejemplo:

  • tablero.append(...) muestra la naturaleza dinámica de list: crece sin declarar tamaño.
  • ESTADOS como 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 set eliminó 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: list de una secuencia dinámica, dict de una tabla asociativa, set de 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 list para 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 dict y set. Ambos usan llaves: {"a": 1} es un diccionario (tiene clave: valor), {"a", "b"} es un conjunto (solo valores). Y ojo: {} a secas crea un diccionario vacío; para un conjunto vacío hay que escribir set().
  • 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 list de 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, un DataFrame, un TreeMap de 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):

  1. Los meses del año en una aplicación de calendario.
  2. El organigrama de una empresa.
  3. La cola de impresión de una oficina.
  4. 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:

  1. Los días de la semana en los que se pueden programar recordatorios (lunes a domingo, fijos).
  2. Los ids de las tareas que el usuario ha marcado como favoritas (sin repetidos, sin orden relevante).
  3. La correspondencia entre cada usuario y su lista de proyectos.
  4. 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:

  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.
  2. 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).
  3. 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).
  4. 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:

  1. tuple: colección fija y ordenada que no debe modificarse: DIAS = ("lunes", ..., "domingo").
  2. set: unicidad garantizada y pertenencia rápida; el orden no importa: favoritas = {4, 8, 15}.
  3. dict: asociación clave → valor, con el usuario como clave y su lista de proyectos como valor: {"ana": ["web", "app"]} (fíjate: un dict que contiene list, composición de estructuras).
  4. 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.

© Copyright 2026. Todos los derechos reservados