Chapter One
What a Data Structure Is, and Why the One You Pick Decides Whether the Program Works
Syllabus topic Module 1, "Abstract Data Type: Different Data Types, different types of data structures & their classifications"
In one line
A data structure is a way of arranging data in memory together with the operations that arrangement makes cheap, and choosing it well is the difference between a program that answers and a program that hangs.
The experiment this whole paper is about
Here is a problem you already have. You hold a list of student roll numbers. Somebody gives you a roll number and asks: is it in the list?
The data is the same in both programs below. The question is the same. The only difference is how the roll numbers are arranged.
import random, time
random.seed(7)
N = 40000
rolls = random.sample(range(1, 10_000_000), N)
queries = random.sample(rolls, 2000)
as_list = list(rolls)
as_set = set(rolls)
start = time.perf_counter()
found = sum(1 for q in queries if q in as_list)
list_seconds = time.perf_counter() - start
start = time.perf_counter()
found_again = sum(1 for q in queries if q in as_set)
set_seconds = time.perf_counter() - start
print("roll numbers held :", N)
print("lookups done :", len(queries))
print("found, list :", found)
print("found, set :", found_again)
print("the answers agree :", found == found_again)
print("set at least 50x faster:", set_seconds * 50 < list_seconds)roll numbers held : 40000
lookups done : 2000
found, list : 2000
found, set : 2000
the answers agree : True
set at least 50x faster: TrueRead the last line again. Both programs are correct. Both give the same answer. One of them does the job at least fifty times faster than the other, and the only thing that changed was the arrangement of the data.
Notice what the program prints and what it refuses to print. It does not print "3,195 times faster", because that number is different on every machine and on every run, and a number a student cannot reproduce is worse than no number. It prints a claim that is true with room to spare, and you can raise the fifty and run it again yourself. Every measurement in this book is printed in that form: something the machine settled, not something the author remembered.
Why that happened
The list keeps the roll numbers in a row. To answer "is 5142337 in here" it has no choice but to walk along, comparing, until it finds the number or reaches the end. With forty thousand numbers, an unsuccessful search compares forty thousand times.
The set computes where the number would be if it were present, and looks only there. It compares once or twice, whatever the size of the collection.
You will build both of those in this paper. The walking search is chapter 16. The computing search is chapter 99, where it is called hashing. Everything between the two is other arrangements, each one cheap at something and expensive at something else.
What a Data Structure Is, and Why the One You Pick Decides Whether the Program Works
The definition, said properly
A data structure is a way of organising data in a computer's memory so that a particular set of operations on it is efficient.
Two halves of that sentence do work, and students usually keep only the first.
A way of organising data in memory. Contiguous cells, or scattered cells joined by addresses, or a branching arrangement. This is the part that is easy to draw.
So that a particular set of operations is efficient. No structure is fast at everything. Every structure in this paper is a bargain: it makes some operations cheap by making others expensive. The array indexes instantly and inserts slowly. The linked list inserts instantly and searches slowly. The hash table finds instantly and cannot tell you what comes next in order.
So the honest question is never "which data structure is best". It is "which operations does my problem do most often, and which structure is cheap at exactly those". A student who leaves this paper with that question in their head has got the value out of it.
A second experiment, so the first is not a fluke
Membership is one operation. Here is a different one, and this time the list wins.
import time
N = 40000
start = time.perf_counter()
row = []
for i in range(N):
row.append(i)
append_seconds = time.perf_counter() - start
start = time.perf_counter()
front = []
for i in range(N):
front.insert(0, i)
insert_seconds = time.perf_counter() - start
print("items added :", N)
print("both hold the same :", len(row) == len(front))
print("front at least 20x slower:", append_seconds * 20 < insert_seconds)items added : 40000
both hold the same : True
front at least 20x slower: TrueSame structure, same number of items, same machine. Adding at the end is cheap; adding at the front is not, because every existing item has to shuffle up one place to make room.
That is the second lesson, and it is sharper than the first: the cost belongs to the pair, the structure and the operation, never to the structure alone. "Lists are fast" is not a statement that means anything. "Adding at the end of a Python list is cheap, and adding at the front is not" is.
What you are going to build
This paper sets eight structures. Here they are in one sentence each, so you know where the road goes.
| Structure | The arrangement | What it is cheap at |
|---|---|---|
| Array | one row of cells, side by side | reaching the nth item |
| Linked list | cells anywhere, each holding the address of the next | inserting and removing |
| Stack | anything, used at one end only | undoing, matching, nesting |
| Queue | anything, added at one end and taken from the other | serving in order of arrival |
| Tree | a branching arrangement | searching, while still inserting |
| Heap | a tree in an array, loosely sorted | finding the largest or smallest |
| Graph | anything joined to anything | relationships, routes, reachability |
| Hash table | a computed address | finding a key, without order |
What a Data Structure Is, and Why the One You Pick Decides Whether the Program Works
Every one of them is built from scratch in this book, run, and measured.
How to read the timings in this book
A timing in seconds is a fact about a machine, not a fact about a structure. This book therefore never says "a linked list takes 0.4 seconds". It says what happens to the time when the data gets bigger, because that is the part that belongs to the structure and travels to your machine.
The three shapes you will meet, over and over:
- Constant. Double the data, the work stays the same. Written O(1).
- Linear. Double the data, double the work. Written O(n).
- Logarithmic. Double the data, add one step. Written O(log n).
The last one is the one worth feeling rather than memorising. Going from a thousand items to a million items multiplies the data by a thousand and adds about ten steps. That is what a tree buys you, and it is why half this paper is trees.
Machine used for every measurement in this book: the timings were produced by the program printed beside them, and the numbers you get will differ. What must not differ is the shape.
Quick revision
- A data structure is an arrangement of data in memory together with the operations that arrangement
makes efficient.
- No structure is good at everything. Every one is a bargain: cheap at some operations, expensive at
others.
- Cost belongs to the pair, structure and operation, never to the structure by itself.
- The right question is which operations the problem does most, not which structure is best.
- Timings in seconds belong to a machine. What belongs to the structure is how the time grows when the
data grows: constant, linear or logarithmic.
- Searching a row of 40,000 numbers one by one against computing where the number lives is the
difference this whole paper is about.
Test yourself
1. Define a data structure in one sentence, including both halves of the definition. A way of organising data in memory together with the operations that arrangement makes efficient. The second half is the half students drop, and it is the half that matters.
2. Is a linked list faster than an array? The question has no answer as asked. A linked list is cheaper at inserting and removing; an array is cheaper at reaching the nth item. Cost belongs to the pair of structure and operation.
What a Data Structure Is, and Why the One You Pick Decides Whether the Program Works
3. In the first experiment both programs printed the same answer. What, then, was wrong with the slow one? Nothing was wrong with its correctness. It was wrong in its choice of arrangement for the operation it did most: it searched by walking when it could have searched by computing.
4. Why does this book refuse to say "a linked list search takes 0.4 seconds"? Because that is a fact about one machine on one day. The fact that belongs to the structure is that doubling the data doubles the work.
5. Going from 1,000 items to 1,000,000 items, how much extra work does an O(log n) operation do? About ten more steps. The data multiplied by a thousand; a logarithmic cost adds about ten.
6. Give one operation that an array is cheap at and a linked list is expensive at, and one the other way round. Reaching the nth item: the array computes the address, the linked list walks to it. Inserting at the front: the linked list moves one link, the array shuffles every element up.