# Data Structures: The Intuition-First Guide

Data structures answer one fundamental question:

> **How should I organize information so that the operations I care about become easy?**

The same data can be stored in many ways.

Suppose we have:

```text
Alice → 92
Bob   → 81
Carol → 95
```

If we frequently ask:

> "What is Bob's score?"

a **hash map** is excellent.

If we repeatedly ask:

> "Who has the highest score?"

a **heap / priority queue** may be better.

If we need:

> "Keep everyone sorted by score while people are continuously added."

a **balanced search tree** may make more sense.

If these people were locations connected by roads, suddenly the natural representation becomes a **graph**.

So don't memorize data structures as isolated definitions.

Think:

```text
Data
  ↓
What operations do I need?
  ↓
What structure makes those operations cheap?
```

* * *

# 1\. Arrays

An array is probably the most fundamental data structure.

Imagine numbered lockers:

```text
index:   0    1    2    3    4
       +----+----+----+----+----+
value: | 12 | 27 |  5 | 91 | 33 |
       +----+----+----+----+----+
```

If you want element `3`, the computer can directly calculate where it lives in memory.

```python
numbers[3]
```

returns:

```text
91
```

This is why array indexing is approximately:

```text
O(1)
```

The computer does **not** search from the beginning.

It effectively calculates:

```text
address = start_address + index × element_size
```

That is the important intuition.

## Arrays are good when

You want:

*   fast random access
    
*   compact storage
    
*   sequential processing
    
*   good CPU cache performance
    
*   matrices, images, sensor buffers, tensors, etc.
    

For example, an RGB image is essentially structured arrays:

```text
image[row][column][channel]
```

A LiDAR scan may also begin life as an array of measurements.

* * *

## The weakness of arrays

Suppose:

```text
[10, 20, 30, 40]
```

and you want to insert `15` after `10`.

You may need:

```text
[10, _, 20, 30, 40]
     ↓
[10, 15, 20, 30, 40]
```

Elements may have to move.

So inserting in the middle is usually:

```text
O(n)
```

* * *

# 2\. Strings

A string is essentially a sequence of characters.

```text
"ROBOT"
```

can be thought of approximately as:

```text
['R', 'O', 'B', 'O', 'T']
```

Strings deserve special treatment because text-processing operations appear everywhere.

Examples:

```python
robot_name = "atlas"
```

We might ask:

```text
length?
contains "las"?
starts with "at"?
find a pattern?
split words?
compare strings?
```

* * *

## Important intuition

A string may look like one object to us:

```text
"autonomous"
```

but algorithms often see a sequence:

```text
a u t o n o m o u s
0 1 2 3 4 5 6 7 8 9
```

Therefore many string algorithms are really clever ways of processing sequences.

This becomes important in:

*   parsers
    
*   compilers
    
*   search engines
    
*   NLP
    
*   log processing
    
*   communication protocols
    

* * *

# 3\. Linked Lists

Imagine train cars.

```text
[A] → [B] → [C] → [D]
```

Each node contains:

```text
value
+
pointer to next node
```

Unlike an array, the nodes do not need to sit next to each other in memory.

A node might conceptually be:

```python
class Node:
    value
    next
```

* * *

## Why linked lists exist

Suppose:

```text
A → B → C
```

and you want:

```text
A → X → B → C
```

You don't shift every element.

You simply change pointers.

```text
A → X
X → B
```

Insertion can therefore be extremely cheap when you already know the location.

* * *

## But there is a tradeoff

Want the 500th element?

An array says:

```text
jump directly there
```

A linked list says:

```text
start at node 1
follow pointer
follow pointer
follow pointer
...
```

So random access is:

```text
O(n)
```

* * *

## Doubly linked lists

Sometimes nodes point both directions:

```text
A ⇄ B ⇄ C ⇄ D
```

Each node stores:

```text
previous
value
next
```

Useful when traversal or removal is needed in both directions.

* * *

# 4\. Stacks

A stack follows:

> **Last In, First Out — LIFO**

Think of plates.

```text
      ┌───┐
top → │ C │
      ├───┤
      │ B │
      ├───┤
      │ A │
      └───┘
```

We added:

```text
A
B
C
```

but remove:

```text
C
B
A
```

Main operations:

```text
push
pop
peek/top
```

usually:

```text
O(1)
```

* * *

## Why stacks matter

Stacks appear naturally whenever things must be completed in reverse order.

Examples:

### Function calls

```python
main()
    A()
        B()
```

The runtime remembers:

```text
main
A
B ← currently executing
```

When `B` finishes:

```text
pop B
```

then return to `A`.

This is essentially the **call stack**.

* * *

### Undo

You perform:

```text
type "hello"
delete word
paste text
```

An editor can push each operation onto a stack.

Undo pops the most recent operation.

* * *

### Depth-first search

DFS naturally uses a stack.

* * *

# 5\. Queues

A queue follows:

> **First In, First Out — FIFO**

Think of people waiting for coffee.

```text
OUT ← [A][B][C][D] ← IN
```

A arrived first, so A gets served first.

Operations:

```text
enqueue
dequeue
front
```

usually:

```text
O(1)
```

* * *

## Where queues appear

Queues are everywhere in systems:

```text
network packets
job scheduling
ROS messages
event processing
task queues
printer jobs
```

And one famous algorithm:

> **Breadth-First Search uses a queue.**

* * *

# Stack vs Queue

This distinction is worth permanently remembering.

```text
STACK
Last thing added comes out first.

A B C
    ↑
    remove C


QUEUE
First thing added comes out first.

A B C
↑
remove A
```

That tiny behavioral difference creates very different algorithms.

* * *

# 6\. Hash Maps

A hash map stores:

```text
key → value
```

Example:

```python
student_scores = {
    "Alice": 95,
    "Bob": 82,
    "Carol": 91
}
```

Then:

```python
student_scores["Bob"]
```

quickly returns:

```text
82
```

Average lookup is approximately:

```text
O(1)
```

This makes hash maps incredibly important.

* * *

# How does that work?

Suppose we have a key:

```text
"Bob"
```

A **hash function** transforms it into a number:

```text
hash("Bob") → 739182...
```

That number determines approximately where the value should be stored.

Conceptually:

```text
"Bob"
   ↓
hash()
   ↓
739182
   ↓
bucket 2
   ↓
82
```

So instead of searching:

```text
Alice?
Carol?
Dave?
Bob!
```

we calculate where Bob should probably live.

* * *

## Collision

Two keys can sometimes map to the same bucket.

```text
hash("Bob")   → bucket 3
hash("John")  → bucket 3
```

This is called a **collision**.

Real hash tables have strategies for handling this.

You don't normally need to think about the implementation details when using one, but understanding collisions explains why hash-map operations are described as:

```text
average O(1)
```

rather than magically guaranteed constant time in every conceivable case.

* * *

## Use hash maps when

You need:

```text
ID → object
name → user
word → count
coordinate → cached value
sensor ID → sensor state
```

Example word frequency:

```python
{
    "robot": 14,
    "sensor": 8,
    "camera": 5
}
```

* * *

# 7\. Sets

A set stores **unique values**.

```python
visited = {"A", "B", "C"}
```

There are no duplicates conceptually.

```text
A
B
C
```

not:

```text
A
A
A
B
C
```

The main question a set answers efficiently is:

> **Have I seen this before?**

Example:

```python
if node in visited:
    ...
```

Usually average:

```text
O(1)
```

with a hash-based set.

* * *

## Hash map vs set

Think:

```text
Hash map:
key → value

Set:
key → exists
```

Example:

```python
phone_numbers["Alice"] = "..."
```

versus:

```python
blocked_users = {"Alice", "Bob"}
```

* * *

# 8\. Heaps

A heap is a special tree designed around one important question:

> **What is the smallest or largest item right now?**

Consider a **min-heap**.

```text
          2
        /   \
       5     8
      / \   / \
     9  12 10  20
```

The rule is:

```text
parent ≤ children
```

Therefore the smallest element is always at the root.

```text
2
```

Importantly:

> A heap is NOT completely sorted.

For example:

```text
5 and 8
9 and 12
```

don't need a global ordering.

Only the parent-child heap rule matters.

* * *

## Why not just sort everything?

Suppose autonomous navigation has candidate actions:

```text
path A cost = 91
path B cost = 12
path C cost = 43
path D cost = 20
```

You repeatedly need:

> Give me the lowest-cost candidate.

Sorting everything again and again would be wasteful.

A min-heap lets us maintain the smallest candidate efficiently.

Typical complexity:

```text
peek minimum      O(1)
insert            O(log n)
remove minimum    O(log n)
```

* * *

# 9\. Priority Queues

A priority queue is an **abstract behavior**:

> Items leave according to priority, not necessarily arrival time.

Example:

```text
Task               Priority
Emergency stop       100
Obstacle avoidance    80
Map update            30
Logging               10
```

The next item should be:

```text
Emergency stop
```

not whichever arrived first.

A **heap is one common implementation of a priority queue**.

So:

```text
Priority Queue = what behavior we want
Heap           = one data structure used to implement it
```

This distinction is important.

* * *

# 10\. Trees

Trees represent **hierarchy**.

Think about a filesystem:

```text
home
├── documents
│   ├── notes.txt
│   └── project.pdf
└── pictures
    ├── robot.png
    └── map.png
```

Or an organization:

```text
CEO
├── Engineering
│   ├── Robotics
│   └── AI
└── Operations
```

Unlike a simple list, one item can lead to multiple children.

* * *

## Core tree terminology

Consider:

```text
          A
        /   \
       B     C
      / \
     D   E
```

`A` is the:

```text
root
```

`B` is a:

```text
child of A
```

`A` is:

```text
parent of B
```

`D` and `E` are:

```text
leaves
```

A path could be:

```text
A → B → E
```

The tree's **height** roughly tells us how many levels deep it goes.

* * *

# 11\. Binary Search Trees — BST

A Binary Search Tree adds an ordering rule.

For every node:

```text
left subtree  < node
right subtree > node
```

Example:

```text
             8
           /   \
          3     12
         / \    / \
        1   6  10  15
```

Want `10`?

Start:

```text
8
```

Since:

```text
10 > 8
```

go right.

```text
12
```

Since:

```text
10 < 12
```

go left.

```text
10
```

Found.

Instead of examining every value, we eliminate large portions of the search space.

* * *

# The dangerous BST problem

Suppose values arrive:

```text
1, 2, 3, 4, 5
```

A naive BST may become:

```text
1
 \
  2
   \
    3
     \
      4
       \
        5
```

That is technically a tree.

But algorithmically it has become almost a linked list.

Search becomes approximately:

```text
O(n)
```

instead of:

```text
O(log n)
```

This leads us to balanced trees.

* * *

# 12\. Balanced Trees

A balanced tree tries to prevent the tree from becoming extremely one-sided.

Healthy:

```text
            8
          /   \
         4     12
        / \    / \
       2   6  10  14
```

Height approximately:

```text
log₂(n)
```

Therefore search, insertion and deletion can remain around:

```text
O(log n)
```

Common examples include:

```text
AVL trees
Red-Black trees
B-trees
B+ trees
```

You don't initially need to memorize every rotation and balancing rule.

The deeper intuition is more valuable:

> **Balanced trees preserve logarithmic search by preventing pathological shape.**

* * *

# 13\. Tries

A trie is a tree specialized for strings or sequences.

Suppose we store:

```text
car
cat
dog
```

The trie looks like:

```text
        root
       /    \
      c      d
      |      |
      a      o
     / \     |
    r   t    g
```

Notice:

```text
car
cat
```

share the prefix:

```text
ca
```

instead of storing that prefix independently twice.

* * *

## Why tries are powerful

Suppose a user types:

```text
auto...
```

You want autocomplete:

```text
autonomous
automation
automobile
```

A trie can quickly navigate the prefix:

```text
a → u → t → o
```

and then explore everything below it.

Useful for:

*   autocomplete
    
*   dictionaries
    
*   routing tables
    
*   prefix matching
    
*   spell checking
    

* * *

# 14\. Graphs

Trees describe hierarchy.

Graphs describe **relationships**.

This is one of the most important data structures in computer science, robotics, networks and AI.

A graph contains:

```text
vertices / nodes
edges / connections
```

Example road network:

```text
      B
     / \
    A   D
     \ /
      C
```

Nodes:

```text
A, B, C, D
```

Edges:

```text
A-B
A-C
B-D
C-D
```

* * *

# Why graphs matter so much

Many real problems are secretly graphs.

```text
Cities        → roads
Computers     → network connections
People        → friendships
Web pages     → hyperlinks
Robot poses   → constraints
Tasks         → dependencies
States        → transitions
Objects       → relationships
```

A robot planning a route through an environment often ends up solving a graph-search problem.

* * *

## Weighted graphs

Edges can have costs.

```text
A ----5---- B
|           |
2           3
|           |
C ----1---- D
```

Weights might represent:

```text
distance
travel time
energy
risk
cost
```

Path planning becomes:

> Find a path whose total edge cost is minimal.

Algorithms such as:

```text
Dijkstra
A*
```

operate on this idea.

* * *

## Directed graphs

Sometimes connections have direction.

```text
A → B
```

does not imply:

```text
B → A
```

Examples:

```text
web links
task dependencies
state transitions
one-way roads
```

* * *

## Graph representation

Two very important representations are:

### Adjacency list

```python
A: [B, C]
B: [A, D]
C: [A, D]
D: [B, C]
```

Excellent for sparse graphs.

### Adjacency matrix

```text
    A B C D
A   0 1 1 0
B   1 0 0 1
C   1 0 0 1
D   0 1 1 0
```

Excellent when direct edge lookup matters and the graph is dense enough.

* * *

# 15\. Disjoint Sets / Union-Find

Suppose you have:

```text
A B C D E F
```

Initially every element is separate:

```text
{A} {B} {C} {D} {E} {F}
```

Then you learn:

```text
A connected to B
B connected to C
```

Now:

```text
{A, B, C} {D} {E} {F}
```

Then:

```text
D connected to E
```

giving:

```text
{A, B, C} {D, E} {F}
```

A **Disjoint Set Union**, or **Union-Find**, efficiently answers:

```text
Are X and Y in the same group?
```

and:

```text
Merge these two groups.
```

The two core operations are:

```text
find(x)
union(a, b)
```

* * *

## Example

Imagine robot-map components.

```text
Region A connected to B
Region B connected to C
Region D connected to E
```

Then asking:

```text
Is A connected to C?
```

should quickly return:

```text
yes
```

while:

```text
Is A connected to E?
```

returns:

```text
no
```

Union-Find is famous for algorithms like:

```text
Kruskal's Minimum Spanning Tree
```

With optimizations such as:

```text
path compression
union by rank/size
```

its operations become extremely close to constant time in practice.

* * *

# 16\. Sparse Representations

This idea becomes extremely important in robotics, machine learning, scientific computing and mapping.

Imagine a huge matrix:

```text
0 0 0 0 0 0
0 0 5 0 0 0
0 0 0 0 0 0
0 2 0 0 0 0
0 0 0 0 0 0
```

Almost everything is zero.

A **dense representation** stores every element.

But why store millions of zeros?

Instead, a sparse representation may store only:

```text
(row=1, col=2, value=5)
(row=3, col=1, value=2)
```

This can drastically reduce:

```text
memory
computation
bandwidth
```

* * *

# Sparse thinking in robotics

Imagine mapping a huge 3D environment.

The world might theoretically contain billions of possible spatial cells.

But perhaps only a tiny fraction are actually occupied.

Instead of storing:

```text
EVERY POSSIBLE LOCATION
```

we often store:

```text
ONLY LOCATIONS WITH USEFUL INFORMATION
```

That idea leads directly into spatial data structures.

* * *

# 17\. Spatial Data Structures

For ordinary data, we often ask:

```text
What value has this key?
```

But robotics constantly asks geometric questions:

```text
What objects are near this point?

What points lie inside this region?

What obstacle is closest to the robot?

Which 3D cells are occupied?

Which LiDAR points belong near each other?
```

These questions require structures designed around **space**.

Important ones include:

```text
KD-trees
quadtrees
octrees
voxel grids
```

* * *

# 18\. KD-Trees

KD means roughly:

> **k-dimensional tree**

They are commonly used for organizing points in multidimensional space.

Suppose we have:

```text
(2,3)
(5,4)
(9,6)
(4,7)
(8,1)
```

Instead of storing only a list and checking every point when asking:

> Which point is closest to `(5,5)`?

a KD-tree repeatedly divides space.

A simplified 2D intuition:

```text
               split x
                  |
        ----------+----------
                  |
          split y |     split y
         ----------     ---------
```

One node may split based on:

```text
x-coordinate
```

the next level based on:

```text
y-coordinate
```

then x again, and so on.

* * *

## Why KD-trees matter

Suppose a LiDAR scan contains:

```text
100,000 points
```

and you ask:

> Which points are nearest to this coordinate?

Checking every point every time may be expensive.

A KD-tree can eliminate large regions that cannot possibly contain the nearest candidate.

This is useful for:

*   nearest-neighbor search
    
*   point clouds
    
*   ICP
    
*   geometric matching
    
*   clustering
    
*   collision queries
    

* * *

# 19\. Quadtrees

A quadtree recursively divides **2D space into four regions**.

Start with:

```text
+-------------------+
|                   |
|      world        |
|                   |
+-------------------+
```

Divide into four:

```text
+---------+---------+
|         |         |
|   NW    |   NE    |
|         |         |
+---------+---------+
|         |         |
|   SW    |   SE    |
|         |         |
+---------+---------+
```

If one region contains lots of detail, divide only that region again.

```text
+---------+---------+
|         |    |    |
|         |----+----|
|         |    |    |
+---------+---------+
|                   |
|                   |
+-------------------+
```

The important intuition is:

> **Spend resolution only where resolution is needed.**

An empty field doesn't need hundreds of tiny cells.

A complicated obstacle-filled region might.

* * *

# 20\. Octrees

An octree is essentially the 3D cousin of the quadtree.

A cube is divided into:

```text
8 smaller cubes
```

because 3D has:

```text
2 × 2 × 2 = 8
```

children.

Conceptually:

```text
Large cube
    ↓
8 cubes
    ↓
interesting cubes subdivide again
    ↓
smaller cubes
```

* * *

## Why octrees matter in robotics

Imagine representing an entire building in 3D.

A naive uniform grid could require enormous amounts of memory.

But much of the volume is:

```text
empty air
```

An octree allows large empty regions to stay coarse while detailed surfaces become fine.

This is useful for:

```text
3D mapping
collision detection
occupancy maps
point clouds
motion planning
```

A famous robotics representation based on this idea is **OctoMap**.

* * *

# 21\. Voxel Grids

A pixel is a small cell in 2D.

A **voxel** is roughly the 3D equivalent.

```text
pixel → picture element
voxel → volume element
```

Imagine the world as tiny cubes:

```text
+---+---+---+
|   |███|   |
+---+---+---+
|   |███|   |
+---+---+---+
|   |   |   |
+---+---+---+
```

Each voxel might store:

```text
occupied
free
unknown
```

or perhaps:

```text
density
color
probability
semantic class
distance-to-surface
```

* * *

## Robotics example

Suppose the robot observes a chair.

Instead of representing the chair as a mathematical mesh, we might mark the 3D cells where its physical matter appears:

```text
empty
empty
chair
chair
empty
...
```

This makes many geometric algorithms easier.

* * *

# Voxel Grid vs Octree

This difference is important.

A normal voxel grid might divide the entire world uniformly:

```text
every cell = 5 cm × 5 cm × 5 cm
```

That is simple.

But potentially huge.

An octree says:

```text
large empty space?
keep it large.

complex geometry?
subdivide it.
```

Therefore:

```text
Voxel grid
→ uniform spatial resolution

Octree
→ adaptive hierarchical resolution
```

* * *

# Quadtree vs Octree

Easy memory trick:

```text
QUAD → 4 children → 2D

OCT  → 8 children → 3D
```

because:

```text
2D:
2 × 2 = 4

3D:
2 × 2 × 2 = 8
```

* * *

# KD-Tree vs Quadtree vs Octree vs Voxel Grid

This is worth understanding rather than memorizing.

| Structure | Main Idea | Typical Use |
| --- | --- | --- |
| KD-tree | Organize points by coordinate splits | nearest-neighbor search |
| Quadtree | Recursively divide 2D regions | maps, 2D spatial indexing |
| Octree | Recursively divide 3D regions | 3D maps, occupancy |
| Voxel grid | Divide 3D space into cells | perception, occupancy, geometry |

Ask yourself:

```text
Do I have POINTS?
→ KD-tree may help.

Do I need adaptive 2D REGIONS?
→ Quadtree.

Do I need adaptive 3D VOLUME?
→ Octree.

Do I want a simple regular 3D lattice?
→ Voxel grid.
```

* * *

# Why spatial structures matter so much in robotics

A normal software application may mostly manipulate:

```text
users
strings
database records
messages
```

A robot must reason about:

```text
SPACE.
```

Its fundamental questions are geometric.

```text
Where am I?

Where is the obstacle?

What exists around me?

Which point belongs to this surface?

Can my robot fit through here?

What is the nearest object?

Which region is unexplored?

Is this location occupied?
```

Consider a simplified autonomous robot pipeline:

```text
Camera / LiDAR
      ↓
Sensor points
      ↓
Point cloud
      ↓
Spatial representation
      ↓
Obstacle / environment understanding
      ↓
Planning
      ↓
Robot movement
```

Different structures may appear throughout the pipeline.

For example:

```text
LiDAR measurements
      ↓
array

Point cloud search
      ↓
KD-tree

3D occupancy
      ↓
voxel grid / octree

Navigation connectivity
      ↓
graph

A* frontier
      ↓
priority queue / heap

visited nodes
      ↓
set

node → metadata
      ↓
hash map
```

Notice something important:

**Real systems don't choose one data structure.**

They combine many structures because each solves a different problem.

* * *

# The Big Picture

You don't need to ask:

> "Which data structure is the best?"

There is no universal best structure.

Ask:

> **Which operation must be fast?**

* * *

If you need:

```text
Get element number i instantly
```

think:

```text
ARRAY
```

* * *

If you need:

```text
Insert/remove through links
```

think:

```text
LINKED LIST
```

* * *

If you need:

```text
Most recently added item
```

think:

```text
STACK
```

* * *

If you need:

```text
Oldest waiting item
```

think:

```text
QUEUE
```

* * *

If you need:

```text
key → value
```

think:

```text
HASH MAP
```

* * *

If you need:

```text
Have I seen this?
```

think:

```text
SET
```

* * *

If you repeatedly need:

```text
Give me the minimum/maximum priority
```

think:

```text
HEAP / PRIORITY QUEUE
```

* * *

If your information is hierarchical:

```text
parent
 ├ child
 └ child
```

think:

```text
TREE
```

* * *

If you need ordered searching:

```text
smaller ← node → larger
```

think:

```text
BST
```

and if reliable performance matters:

```text
BALANCED TREE
```

* * *

If you need prefix lookup:

```text
"auto..."
```

think:

```text
TRIE
```

* * *

If things are connected in arbitrary ways:

```text
A ↔ B
↕   ↕
C ↔ D
```

think:

```text
GRAPH
```

* * *

If you repeatedly merge connected groups:

```text
{A,B} + {C,D}
```

think:

```text
DISJOINT SET / UNION-FIND
```

* * *

If most possible values are empty or zero:

```text
0 0 0 0 X 0 0 0
```

think:

```text
SPARSE REPRESENTATION
```

* * *

If the problem is geometric:

```text
nearest point
occupied region
3D environment
```

start thinking about:

```text
KD-trees
quadtrees
octrees
voxel grids
```

* * *

# A Small Complexity Cheat Sheet

You don't need to blindly memorize this table. Understand **why** the operations have these costs.

| Structure | Important Operation | Typical Cost |
| --- | --- | --- |
| Array | index access | O(1) |
| Array | middle insertion | O(n) |
| Linked list | access by position | O(n) |
| Linked list | known-position insert/remove | O(1) |
| Stack | push/pop | O(1) |
| Queue | enqueue/dequeue | O(1) |
| Hash map | lookup | O(1) average |
| Hash set | membership | O(1) average |
| Heap | minimum/maximum peek | O(1) |
| Heap | insert/remove root | O(log n) |
| Balanced BST | search/insert/delete | O(log n) |
| Trie | lookup | roughly O(length of key) |
| Graph traversal | BFS/DFS | O(V + E) |
| Union-Find | union/find | almost O(1) amortized |

For spatial structures, complexity depends heavily on:

```text
dimension
distribution of points
tree balance
query type
```

so don't reduce them to one magical Big-O number.

* * *

# One Deeper Lesson

Data structures are not merely containers.

They encode **assumptions about the problem**.

A queue says:

> Order of arrival matters.

A priority queue says:

> Importance matters more than arrival.

A BST says:

> Ordering matters.

A hash map says:

> Exact identity matters.

A graph says:

> Relationships matter.

A KD-tree says:

> Geometric proximity matters.

An octree says:

> Space has detail at different scales.

That is the deeper way to learn data structures.

* * *

# Final Mental Model

When encountering a new engineering problem, don't immediately ask:

> "Which data structure should I use?"

First identify the operations:

```text
What do I need to retrieve?

What do I need to update?

What do I need to search?

Does ordering matter?

Does priority matter?

Does connectivity matter?

Does geometric distance matter?

Is the data sparse?

How large can the data become?
```

Then choose the representation.

Because in computer science:

> **The way you represent the problem often determines how easily you can solve it.**

And in robotics this becomes even more literal:

> **Representing the world correctly is often half the problem of understanding and navigating it.**
