You already know what a data structure is and why choosing well matters. The next natural step is to get to know the catalog: which structures exist and how are they classified? This lesson is the map of the course: we will introduce the major families of structures (linear and nonlinear, static and dynamic, homogeneous and heterogeneous), see what role each will play in TaskFlow, and review the structures Python ships with out of the box, which will be our starting point. We won't go deep into any of them — each has its own module — but by the end you will be able to place any structure on the map and understand the itinerary we will follow.

Contents

  1. Classification 1: linear vs nonlinear
  2. Classification 2: static vs dynamic
  3. Classification 3: homogeneous vs heterogeneous
  4. The course catalog and its role in TaskFlow
  5. Python's built-in structures: our starting point

Classification 1: linear vs nonlinear

The first question you can ask of any structure is: how do its elements relate to one another?

  • In a linear structure, the elements form a sequence: each element has (at most) one predecessor and one successor. It is the "one after another" relationship.
  • In a nonlinear structure, an element can relate to several at once: hierarchies (a parent with several children) or networks (arbitrary connections between nodes).
graph TB
    subgraph Linear
        A1[Task 1] --> A2[Task 2] --> A3[Task 3] --> A4[Task 4]
    end
    subgraph Nonlinear: hierarchy
        B1[Work] --> B2[Client A]
        B1 --> B3[Client B]
        B2 --> B4[Invoices]
        B2 --> B5[Meetings]
    end
    subgraph Nonlinear: network
        C1[Task A] --> C2[Task B]
        C1 --> C3[Task C]
        C2 --> C4[Task D]
        C3 --> C4
    end

All three patterns show up naturally in TaskFlow:

  • The task board is linear: tasks come in order, one after another.
  • The categories are hierarchical: "Work" contains "Client A", which contains "Invoices".
  • The dependencies are a network: task D depends on B and C, which in turn depend on A.

Lists, stacks, and queues are linear (modules 2 to 4). Trees (hierarchies, module 6) and graphs (networks, module 7) are nonlinear. Hash tables (module 5) are a case apart: their elements maintain no ordering relationship with one another — neither sequence nor hierarchy; what defines them is the direct association between each key and its value.

The classification matters because it determines how the structure is traversed: a sequence is traversed from start to finish; a hierarchy or a network demands more elaborate traversal strategies (we'll see them in their modules).

Classification 2: static vs dynamic

The second question: can the structure's size change during execution?

  • A static structure has a fixed size, decided when it is created. It occupies a block of memory of known size and neither grows nor shrinks.
  • A dynamic structure grows and shrinks as elements are inserted or removed, adapting its memory usage at runtime.
Aspect Static Dynamic
Size Fixed at creation Changes during execution
Memory Reserved all at once, contiguous Requested and released on the fly
Main advantage Simplicity and very fast access Flexibility: no need to predict the size
Typical risk Running short or wasting space Extra memory-management overhead
Classic example Fixed-size array (C, Java) Linked list, Python list

The canonical example of a static structure is the fixed-size array, common in languages like C or Java: you request room for exactly 100 elements and that's what you get. In Python almost everything you will use is dynamic — a list grows without you worrying about a thing — but the distinction remains crucial for two reasons:

  1. Python's dynamic structures are built on top of static mechanisms underneath, and that "underneath" explains their costs (we'll see it in lesson 01-05 with arrays and memory).
  2. As soon as you step outside Python (databases, embedded systems, other languages), fixed sizes reappear.

For TaskFlow: the number of tasks is unpredictable and changes constantly, so we will need dynamic structures almost always. In contrast, something like the three possible statuses of a task (pending, in_progress, done) is a fixed set that never grows: a static, immutable structure (a tuple, as we'll see below) represents it better.

Classification 3: homogeneous vs heterogeneous

Third question: are all the elements of the same type?

  • A homogeneous structure only admits elements of a single type: all integers, all strings...
  • A heterogeneous structure mixes types: an integer next to a string next to an object.
# Homogeneous: task ids, all integers
pending_ids = [4, 8, 15, 16, 23]

# Heterogeneous: a task with fields of different types
task = {
    "id": 42,                      # integer
    "title": "Migrate server",     # string
    "priority": "high",            # string
    "completed": False,            # boolean
    "tags": ["infra", "urgent"],   # another structure inside!
}

In strictly typed languages (C, Java), arrays are homogeneous by obligation. Python is flexible: a list accepts any mixture. But the fact that you can mix doesn't mean you should: in professional practice, collections tend to stay homogeneous ("a list of tasks", "a set of ids") and heterogeneity is reserved for representing records with named fields, like the task dictionary in the example. This discipline makes the code predictable: if you know that pending_ids only contains integers, you can operate confidently on any of its elements.

Also notice the last line of the example: "tags" contains a list inside the dictionary. Structures compose with one another, and real applications — TaskFlow included — are always compositions: a list of dictionaries, a dictionary of lists, a tree whose nodes contain queues...

The course catalog and its role in TaskFlow

With the three classifications in hand, we can now present the complete catalog of structures we will study, each with the TaskFlow need it will solve:

Structure Family The idea in one sentence Use in TaskFlow Module
List Linear, dynamic Sequence of elements in order The task board 2
Stack Linear, dynamic Last in, first out (LIFO) The "undo" of actions 3
Queue Linear, dynamic First in, first out (FIFO) Processing notifications 4
Hash table Associative, dynamic Each key leads directly to its value Instant lookup by id 5
Tree Nonlinear (hierarchy), dynamic Parent nodes with child nodes Categories and subcategories 6
Graph Nonlinear (network), dynamic Nodes freely connected to one another Dependencies between tasks 7

Two observations about the table:

  • The terms LIFO (Last In, First Out) and FIFO (First In, First Out) are the only new "jargon": picture them as the stack of plates and the supermarket line from lesson 01-01, and you'll have 90% of the intuition.
  • The order of the modules is no accident: it goes from simplest to richest. Stacks and queues are built from ideas in lists; trees generalize the idea of "an element pointing to others"; graphs generalize trees. Each module builds on the previous one, just as TaskFlow will grow piece by piece.

The complete journey, seen as an itinerary:

graph LR
    L[Lists<br/>M2] --> P[Stacks<br/>M3] --> C[Queues<br/>M4] --> H[Hash tables<br/>M5] --> A[Trees<br/>M6] --> G[Graphs<br/>M7]

Remember that this lesson is only the map: the precise definition of each structure, its operations, implementations, and costs are developed in its corresponding module.

Python's built-in structures: our starting point

Python ships with four data structures that we will use constantly, both in their own right and to build the structures in the catalog. It's worth being clear about the role of each:

Structure Syntax Ordered? Mutable? Duplicates? Typical use
list [1, 2, 3] Yes (by position) Yes Yes Sequences that change
tuple (1, 2, 3) Yes (by position) No Yes Fixed records, constants
dict {"a": 1} By insertion Yes Keys no Key → value associations
set {1, 2, 3} No Yes No Membership and uniqueness

("Mutable" means it can be modified after creation; "ordered", that its elements maintain a defined order.)

Let's see them in action with TaskFlow data:

# list: the board draft — ordering and constant changes
board = ["Design logo", "Write report", "Send invoice"]
board.append("Call client")           # grows dynamically

# tuple: the possible statuses — a FIXED set nobody should touch
STATUSES = ("pending", "in_progress", "done")
# STATUSES.append("other")  -> AttributeError: tuples don't change

# dict: a task as a heterogeneous record with named fields
task = {"id": 7, "title": "Send invoice", "status": "pending"}
print(task["title"])                  # access by key, not by position

# set: unique tags used in the project — no duplicates
tags = {"urgent", "client", "urgent"}
print(tags)                           # {'urgent', 'client'} — the duplicate vanishes

Points worth highlighting in the example:

  • board.append(...) shows the dynamic nature of list: it grows without declaring a size.
  • STATUSES as a tuple is the correct static, immutable choice for data that must not change; if someone tries to modify it, Python raises an error, protecting the program. The all-caps naming convention signals "this is a constant".
  • The set removed the duplicate "urgent" automatically: uniqueness is part of its contract.
  • These four structures are, in the terms of lesson 01-01, highly polished implementations of certain ADTs: list of a dynamic sequence, dict of an associative table, set of a mathematical set. In the coming modules we will use them both directly and as "building material" to implement stacks, queues, trees, and graphs.

What about the structures Python doesn't ship with (linked lists, trees, graphs)? We will build them ourselves with classes, exactly as we did with ListStack in lesson 01-01. That's where much of the course's value lies: not just using structures, but knowing how to make them.

Common Mistakes and Tips

  • Using list for everything. It's the number one vice of the Python beginner: the list is so convenient it becomes a universal hammer. Before typing [], ask yourself: do I need order? (if not, maybe set), do I access by name? (maybe dict), is the data fixed? (maybe tuple).
  • Confusing the syntax of dict and set. Both use curly braces: {"a": 1} is a dictionary (it has key: value), {"a", "b"} is a set (values only). And watch out: a bare {} creates an empty dictionary; for an empty set you must write set().
  • Believing the classifications are rigid compartments. They are axes of analysis, not exclusive drawers: the same structure can be described along all three axes at once (a Python list is linear, dynamic, and potentially heterogeneous), and hash tables don't quite fit on the linear/nonlinear axis.
  • Tip: when you come across a new structure in any language or library (a deque, a DataFrame, a Java TreeMap...), place it along the three axes of this lesson and figure out which ADT it answers to. It's the fastest way to "read" an unfamiliar structure.

Exercises

Exercise 1: classifying structures

Classify each scenario along the axes we've seen (linear/nonlinear; and where it makes sense, static/dynamic and homogeneous/heterogeneous):

  1. The months of the year in a calendar application.
  2. A company's organizational chart.
  3. An office's print queue.
  4. The friendship connections of a social network.

Exercise 2: choosing the built-in structure

For each TaskFlow need, choose the most suitable Python built-in structure (list, tuple, dict, or set) and justify it in one sentence:

  1. The days of the week on which reminders can be scheduled (Monday to Sunday, fixed).
  2. The ids of the tasks the user has marked as favorites (no repeats, no relevant order).
  3. The mapping between each user and their list of projects.
  4. The history of task titles viewed, in order, with possible repeats.

Exercise 3: composing structures

Write in Python the representation of a mini TaskFlow board with these requirements: there must be three fixed status columns (pending, in_progress, done); each column holds its tasks in order; each task has an id, a title, and a set of tags with no duplicates. Create the board with at least two tasks and write one line of code that adds a tag to an existing task. State which built-in structure you used at each level and why.

Solutions

Solution 1:

  1. Months of the year: linear (an ordered sequence), static (there are always 12), and homogeneous (all strings). In Python, a tuple would be the natural fit.
  2. Organizational chart: nonlinear, hierarchical (each person has a manager and may have several reports): the shape of a tree. Dynamic (the workforce changes).
  3. Print queue: linear and dynamic; arrival order is the essential relationship (FIFO). Homogeneous (they are all print jobs).
  4. Friendships: nonlinear, a network (each person connects to many others with no hierarchy): the shape of a graph. Dynamic.

Solution 2:

  1. tuple: a fixed, ordered collection that must not be modified: DAYS = ("monday", ..., "sunday").
  2. set: guaranteed uniqueness and fast membership; order doesn't matter: favorites = {4, 8, 15}.
  3. dict: key → value association, with the user as key and their project list as value: {"anna": ["web", "app"]} (notice: a dict containing a list — structure composition).
  4. list: an ordered, dynamic sequence with duplicates allowed: exactly the list's contract.

Solution 3:

board = {
    "pending": [
        {"id": 1, "title": "Design logo", "tags": {"design", "client"}},
        {"id": 2, "title": "Send invoice", "tags": {"admin"}},
    ],
    "in_progress": [],
    "done": [],
}

# Add a tag to the task with id 1 (first one in "pending"):
board["pending"][0]["tags"].add("urgent")

Level-by-level justification: a dict for the columns (access by status name); a list per column (tasks keep an order and the collection grows and shrinks); a dict per task (a heterogeneous record with named fields); a set for the tags (automatic uniqueness). Four built-in structures composing to model a real domain. Note: the three status keys are fixed, but a dict is the practical option for access by name; the immutability of "there are only three statuses" is something we will enforce with other techniques later on.

Conclusion

You now have the complete map: structures are classified by how their elements relate (linear like lists, stacks, and queues; nonlinear like trees and graphs; associative like hash tables), by whether their size is fixed or variable (static vs dynamic), and by whether they mix types (homogeneous vs heterogeneous). You know what role each will play in TaskFlow and you have Python's four built-in structures — list, tuple, dict, set — as both starting material and building material.

But the map is missing one dimension: the numbers. We said the hash table looks things up "instantly" and the list "scans everything"... how do we express that precisely, so we can compare structures rigorously? That is the purpose of the next lesson: Big O notation, the universal language for talking about efficiency that we will use for the entire rest of the course.

© Copyright 2026. All rights reserved