← Big Ideas of Computer Science
An interactive field guide

The big ideas of computer science

A computer only flips bits, very fast. What makes it useful is a set of ideas about what can be computed, how to do it quickly, how to build machines that keep working when parts fail, and how to keep secrets. Here are twelve of them. Each one comes with a simulation you can run in your browser.

Conway's Game of Life. Each cell follows four simple rules, yet the grid can simulate any computer.
Part I

What a computer is

In the 1930s, before any electronic computer existed, mathematicians asked what it means to compute something. Their answers, along with Claude Shannon's theory of information a decade later, still define what computers can and can't do.

01

Everything is bits

Numbers, text, images and programs are all stored as patterns of 0s and 1s. What a pattern means depends entirely on how you read it.

A switch is either off or on, so the simplest thing an electronic circuit can store is a single bit: 0 or 1. String eight bits together and you have a byte, with 2 × 2 × … × 2 = 256 possible patterns. Every file on your computer is a long sequence of bytes.

The bits themselves carry no meaning. The pattern 01000001 is the number 65, the letter "A" in the ASCII text code, or a dark grey pixel, depending on which program reads it. The same goes for negative numbers. Most computers use two's complement, in which 11111111 means −1, so the same byte can be 255 or −1.

n bits can represent 2n different values 8 bits → 256, 32 bits → about 4.3 billion, 64 bits → about 18 quintillion

History

Gottfried Leibniz published binary arithmetic in 1703, and George Boole his algebra of true and false in 1854. In his 1937 master's thesis, Claude Shannon showed that Boole's algebra could describe switching circuits, which is the foundation of digital logic design. ASCII was standardized in 1963, and Unicode, which covers the world's writing systems, in 1991.

Watch out

Fixed-width numbers wrap around. In 1996 the first Ariane 5 rocket destroyed itself about 40 seconds after launch because a 64-bit number was converted to a 16-bit integer that couldn't hold it. In 2014 the view count for "Gangnam Style" passed 2,147,483,647, the largest signed 32-bit number, and YouTube had to switch to 64-bit counters.

Try it · Flip the bits of one byte
Read as 0 to 255 Read as −128 to 127
Unsigned Signed As text As a grey pixel
Click +1 at 127 or at 255. The bits roll over like a car's odometer. Read as unsigned, the number jumps from 255 to 0. Read as signed, it jumps from 127 to −128.
02

Universal machines & the halting problem

A very simple machine, given the right program, can compute anything any computer can. But no program can tell, for every program, whether it will ever finish.

In 1936 Alan Turing described an imaginary machine with a long tape of symbols, a head that reads and writes one cell at a time, and a small table of rules: "in state A, reading 0, write 1, move right, switch to state B." He showed that one such machine, the universal machine, can read the rule table of any other machine from its tape and imitate it. That's the idea behind the stored-program computer, in which programs are just more data.

Turing also proved a limit. Suppose some program H could look at any program and its input and say whether it eventually halts. Build a program D that asks H about itself and does the opposite: if H says "D halts", D loops forever, and otherwise it halts. Whatever H answers about D is wrong, so H can't exist.

D halts ⇔ H says D doesn't halt So no program can decide halting for all programs

History

Turing's paper "On Computable Numbers" appeared in 1936, months after Alonzo Church reached the same limit with his lambda calculus. John von Neumann's 1945 report on the EDVAC described a stored-program computer. Tibor Radó introduced the "busy beaver" game in 1962: which machine with n states runs longest before halting? The 5-state answer, 47,176,870 steps, was only proved in 2024, by an online collaboration with a computer-checked proof.

Watch out

Undecidable doesn't mean you can never tell. Plenty of individual programs can be proved to halt or loop. It means no single method works for all programs, which is why tools that hunt for bugs must sometimes answer "don't know."

Try it · Run a Turing machine
Steps 1s on tape Status
Each machine starts on a blank tape of 0s. The fourth machine has a halt rule, but it never reaches it. Watching it run, you can't be sure of that, which is the halting problem in miniature.
03

Information & compression

Information can be measured in bits, and no lossless code can, on average, beat that measure. Predictable data compresses well. Random data hardly compresses at all.

In 1948 Claude Shannon defined the information in a message as how surprising it is. A symbol that occurs with probability p carries log₂(1/p) bits. Averaged over the symbols, this gives the entropy, the minimum number of bits per symbol any lossless code needs on average.

Text stored as ASCII uses 8 bits for every character, but "e" is far more common than "z." Huffman coding gives common symbols short codes and rare ones long codes, and gets within one bit per symbol of the entropy. Real compressors such as ZIP's DEFLATE also replace repeated phrases with short back-references, which is why text and code shrink so well.

entropy = Σ p × log₂ 1p bits per symbol No lossless code can average fewer bits than this

History

Shannon's "A Mathematical Theory of Communication" appeared in 1948. David Huffman found his optimal code in 1952 as an MIT student, in a term paper he wrote instead of taking the final exam. Abraham Lempel and Jacob Ziv published the LZ77 algorithm in 1977, and it is still inside ZIP, PNG and gzip.

Watch out

No compressor can shrink every file. There are 2n files of n bits but fewer shorter ones, so if some files get smaller, others must get bigger. Compression works only because real data has patterns. Already-compressed or encrypted data looks random and won't shrink further.

Try it · Compress some text
How often the character appears Number above each bar: Huffman code length in bits
As 8-bit text Huffman coded Entropy limit
Part II

Algorithms

An algorithm is a precise recipe for solving a problem. Two recipes for the same problem can differ in speed by a factor of millions, and that gap usually matters more than how fast the hardware is.

04

Growth rates & binary search

What matters about an algorithm is how its running time grows with the size of the input. An algorithm that halves the problem at each step needs about 30 steps for a billion items.

To find a name in an unsorted list, you may have to check every entry: for n entries that's up to n steps. If the list is sorted, open it in the middle. If the name comes earlier, throw away the second half, and repeat. Each step halves what's left, so it takes at most about log₂ n steps. This is binary search.

Computer scientists describe growth with big-O notation. Linear search is O(n), binary search is O(log n), and comparing every pair of items is O(n²). Constant factors (a faster chip, a cleverer loop) change the time by a fixed ratio. A better growth rate changes it by a ratio that keeps widening as the input grows.

steps for binary search ≈ log₂ n 1,000 items → 10 steps, 1 million → 20, 1 billion → 30

History

John Mauchly described binary search in 1946. The O notation comes from number theory (Paul Bachmann, 1894, and Edmund Landau), and Donald Knuth made it standard in computer science in the 1970s.

Watch out

Simple algorithms are easy to get wrong. In 2006 Joshua Bloch reported that the binary search in Java's standard library, and in many textbooks, failed on arrays of more than about a billion elements: computing the midpoint as (low + high) / 2 overflowed a 32-bit integer (idea 1).

Try it · Search a sorted list
Still in play Middle item checked
Linear search, worst case Binary search, this time Binary search, worst case
05

Divide and conquer

Split a problem in half, solve each half, and combine the answers. For sorting, this turns about n² comparisons into about n log₂ n.

Insertion sort is how most people sort a hand of cards: take each new item and slide it left past everything bigger. It's simple, but on a shuffled list each item slides past about half of the ones before it, so it makes about n²/4 comparisons.

Merge sort splits the list in half, sorts each half the same way, then merges the two sorted halves by repeatedly taking the smaller front item. Merging is quick, and there are only log₂ n levels of halving, so the total is about n log₂ n comparisons. For a million items, that's 20 million instead of 250 billion.

insertion sort ≈ n²4  vs.  merge sort ≈ n log₂ n comparisons No method that only compares items can do better than about n log₂ n

History

John von Neumann wrote a merge sort for the EDVAC in 1945. Tony Hoare invented quicksort in 1959, another divide-and-conquer sort that is very fast in practice. The same split-solve-combine pattern gives fast multiplication of large numbers (Karatsuba, 1960) and the fast Fourier transform (Cooley and Tukey, 1965).

Watch out

Growth rates describe large inputs. On short or nearly sorted lists, insertion sort wins because it does so little bookkeeping. Python's and Java's built-in sort, Timsort, uses insertion sort for short runs and merging for the rest.

Try it · Race two sorting algorithms
Insertion sort comparisons Merge sort comparisons
Both sorts run at the same number of comparisons per second. Double the number of items and insertion sort's count roughly quadruples, while merge sort's only slightly more than doubles. Try "nearly sorted" to see insertion sort win.
06

Graph search

Road maps, computer networks and friendships are all graphs: points joined by links. Exploring a graph in order of distance finds the shortest route, and a good guess about direction finds it with much less exploring.

A graph is a set of nodes and the edges between them. Many problems become graph problems: what's the fastest route home, how does a packet cross the internet, how many handshakes separate you from a stranger.

Breadth-first search explores outward from the start in rings: first everything one step away, then two steps, and so on. The first time it reaches the goal, it has found a shortest path. Dijkstra's algorithm does the same when edges have different lengths. A* adds an estimate of the remaining distance, such as the straight-line distance, so it explores towards the goal first. As long as the estimate never overstates the real distance, A* still finds a shortest path.

A* explores nodes in order of: distance so far + estimated distance remaining With an estimate of 0 it is Dijkstra's algorithm

History

Leonhard Euler founded graph theory in 1736 with the bridges of Königsberg. Edsger Dijkstra designed his shortest-path algorithm in 1956, by his account in about twenty minutes at a café in Amsterdam, and published it in 1959. A* came from the Shakey robot project at the Stanford Research Institute (Hart, Nilsson and Raphael, 1968).

Watch out

Dijkstra's algorithm assumes no edge has negative length. A* is only guaranteed to find the shortest path if its estimate never overstates the remaining distance. Overestimates make it faster, but it may then settle for a longer route.

Try it · Find a path through a maze
Wall (click to toggle) Explored Shortest path found
Cells explored Path length
07

Hard problems: P vs. NP

For many important problems, checking a proposed answer is easy but finding the best one seems to require trying an astronomical number of possibilities. Whether that's really necessary is the biggest open question in computer science.

A salesperson must visit n cities and return home by the shortest route. With 10 cities there are 181,440 distinct round trips. With 25 there are about 3 × 10²³, and at a billion trips per second checking them all would take about ten million years. Given a route and a target length, though, you can check it in moments.

P is the class of problems that can be solved in time growing like a polynomial in the input size. NP is the class where a proposed solution can be checked in polynomial time. The travelling salesman problem, scheduling, Sudoku on large boards and thousands of others are NP-complete: a fast algorithm for any one of them would give fast algorithms for all of NP. Nobody has found one, and nobody has proved one can't exist.

round trips through n cities = (n − 1)!2 Fix the start city, and count each loop once in either direction

History

Stephen Cook (1971) and Leonid Levin (1973) independently defined NP-completeness, and Richard Karp showed in 1972 that 21 well-known problems were NP-complete. In 2000 the Clay Mathematics Institute made P vs. NP one of its seven Millennium Prize Problems, with a $1 million prize.

Watch out

NP-complete means hard in the worst case, not hopeless in practice. Heuristics often find routes within a few percent of the best, and exact solvers have handled real instances with tens of thousands of cities. In 2006 the Concorde solver proved an optimal tour through 85,900 points of a chip layout.

Try it · Plan a sales trip
Best route (checked every trip) Greedy: always go to the nearest unvisited city
Round trips to check Best length Greedy length
Part III

Building systems

Real computers are built from parts that are too slow, too busy, or occasionally wrong. Systems design is about making the whole behave better than its parts.

08

Caching & locality

Fast memory is small and expensive, and large memory is slow. Keeping recently used data in a small fast cache makes the whole system nearly as fast as the cache, because programs tend to reuse the same data.

Reading from a processor's first-level cache takes about a nanosecond. Main memory takes about 100 nanoseconds, a solid-state drive tens of thousands, and a network round trip across a continent tens of millions. Each level is bigger, cheaper and slower than the one above.

A cache keeps copies of recently used data in the faster level. It works because of locality: programs tend to reuse data they used recently and data stored nearby. When the cache is full, a common rule is to evict the least recently used (LRU) item. Web browsers, content delivery networks and databases all rely on caches.

average access time = hit rate × fast time + miss rate × slow time With 1 ns and 100 ns, a 99% hit rate gives about 2 ns

History

Maurice Wilkes proposed "slave memories" in 1965, and IBM's System/360 Model 85 (1968) was the first commercial computer with a cache. László Bélády worked out the optimal eviction rule in 1966, and Peter Denning described the "working set" of a program in 1968.

Watch out

LRU fails badly on loops that are slightly too big. If a program cycles through 11 items with a cache of 10, every access evicts the item that's needed next, and the hit rate is zero. Set the pattern to "loop" in the lab and move the cache size across the working set.

Try it · Size a cache
Hit rate Average access time
The curve shows the hit rate of an LRU cache of every size on the same 20,000 accesses. When a few items are popular, a small cache catches most of the traffic.
09

Queues & load

As a server gets busier, waiting time doesn't grow steadily. It explodes. When requests arrive at random, a server that's 90% busy makes each one take ten times as long as the work itself.

Requests to a web server, jobs at a printer and cars at a toll booth arrive at random. Even if the server can handle the average load, arrivals bunch up, and a queue forms. The fraction of time the server is busy is its utilization.

For random arrivals and random service times, the average time a request spends in the system is the service time divided by (1 − utilization). At 50% utilization that's 2× the service time, at 90% it's 10×, and at 99% it's 100×. This is why well-run systems keep spare capacity, and why a small traffic increase can make a busy site suddenly unusable.

time in system = service time1 − utilization For random (Poisson) arrivals and service times (the M/M/1 queue)

History

Agner Krarup Erlang, an engineer at the Copenhagen Telephone Company, founded queueing theory in 1909 to work out how many lines an exchange needed. John Little proved in 1961 that the average number in a system equals the arrival rate times the average time spent there (L = λW), for almost any queue.

Watch out

The exact numbers depend on how variable arrivals and service are. Perfectly regular arrivals and service would never queue at all, and more variability makes waits worse. But in every case, waits grow without limit as utilization approaches 100%.

Try it · Run a busy server
Theory Your simulations Requests in system (second chart)
Average time in system Theory Little's law check, L vs. λW
10

Error-correcting codes

Add a few carefully chosen extra bits, and the receiver can find and fix errors on its own, without asking for the message again.

Every channel corrupts some bits: radio static, scratches on a disc, cosmic rays hitting memory. The crudest fix is to send every bit three times and take a majority vote. That fixes any single error in each group, but it triples the length of the message.

Richard Hamming found something better. His (7,4) code adds three parity bits to every four data bits, each checking a different overlapping subset. If one bit flips, the pattern of failed checks spells out its position in binary, so the receiver can flip it back. That corrects any single error with 75% overhead instead of 200%. Modern codes, used in phones, Wi-Fi, QR codes and spacecraft, get close to the theoretical limit Shannon proved in 1948.

Hamming (7,4): 4 data bits + 3 parity bits; any 1 flipped bit in 7 is corrected The failed parity checks, read as a binary number, give the position of the error

History

Hamming, frustrated that the relay computers at Bell Labs stopped at the first error over the weekend, published his codes in 1950. Reed–Solomon codes (1960) protect CDs, QR codes and the Voyager probes' pictures. Your computer's ECC memory uses Hamming-style codes.

Watch out

A code designed to fix one error per block can make things worse when two occur: it "corrects" the wrong bit. Turn the noise in the lab up past about 20% and Hamming decoding does worse than sending no code at all. Codes must be matched to how noisy the channel really is.

Try it · Send a picture over a noisy line
Correct pixel Wrong pixel after decoding
Wrong pixels, no code Repeat ×3 Hamming (7,4)
Part IV

Secrets & learning

Two of the ideas that shape how computers touch daily life: mathematics that lets strangers trust each other online, and programs that learn their behaviour from data instead of being told.

11

Public-key cryptography

Some operations are easy to do and practically impossible to undo without a secret. That lets two strangers set up a private conversation over a channel everyone can hear.

For most of history, two people who wanted to communicate secretly first had to meet and agree on a key. Public-key cryptography removes that step. You publish a public key anyone can use to encrypt a message to you, and keep a private key that alone can decrypt it.

In RSA, the public key includes a number n = p × q, the product of two large secret primes. Multiplying them is easy. Recovering them from n is, as far as anyone knows, infeasible when each has hundreds of digits. Encryption raises the message to a power and keeps the remainder after dividing by n. Decryption needs a different power that can only be computed from p and q.

encrypt: c = me mod n    decrypt: m = cd mod n d is chosen so that e × d leaves remainder 1 when divided by (p − 1)(q − 1)

History

Whitfield Diffie and Martin Hellman published public-key key exchange in 1976. Ron Rivest, Adi Shamir and Leonard Adleman invented RSA in 1977. It later emerged that James Ellis, Clifford Cocks and Malcolm Williamson at Britain's GCHQ had found the same ideas between 1970 and 1974, in secret.

Watch out

The lab's numbers are tiny, so anyone could factor n. Real keys use primes with hundreds of digits. In 1994 Peter Shor showed that a large quantum computer could factor quickly, and in 2024 the US standards body NIST published its first "post-quantum" encryption standards in response. Textbook RSA as shown here is also insecure without randomized padding.

Try it · Make a toy RSA key
Public key (n, e) Private key d Encrypted Decrypted
Each dot is one possible message and its encryption. The scrambling looks random, yet with d every dot maps back exactly. To an outsider, the only route to d is factoring n.
12

Learning from examples

Instead of writing rules by hand, a program can infer them from labelled examples. The hard part is doing well on examples it hasn't seen, not on the ones it was trained on.

Nobody can write down rules for recognizing a cat in a photo, but it's easy to collect photos labelled "cat" and "not cat." Machine learning builds a program from such examples. The simplest method is nearest neighbours: to label a new point, find the k closest training examples and take a vote.

With k = 1 the method memorizes the training data perfectly, including its mistakes and noise. It scores 100% on the examples it has seen but worse on new ones. This is overfitting. Larger k averages over more neighbours and gives smoother boundaries, but too large and it misses real detail. Every learning method, up to today's neural networks, has to balance fitting the data against generalizing beyond it, and is judged on held-out test data.

judge a model by its accuracy on new data, never on the data it learned from

History

Evelyn Fix and Joseph Hodges proposed nearest-neighbour classification in 1951, and Thomas Cover and Peter Hart proved in 1967 that, with enough data, its error rate is at most twice the best possible. Frank Rosenblatt built the perceptron in 1958. Training multi-layer neural networks by backpropagation was popularized in 1986, and their 2012 success at image recognition (AlexNet) began the deep-learning era.

Watch out

A model learns whatever patterns are in its training data, including biases and accidents of how the data was collected. A model can test well and still fail when the world it's used in differs from the one it learned from.

Try it · Train a nearest-neighbour classifier
Class A Class B True boundary
Accuracy on training data On 2,000 new points Best possible
Putting it together

Three threads run through all twelve ideas

Representation and its limits

Bits, universal machines and entropy (ideas 1–3) show that anything describable can be computed on one kind of machine, and they also set hard limits: overflow, undecidability, and data that can't be compressed.

Growth beats speed

Binary search, merge sort, graph search, NP-hardness and queueing (ideas 4–7, 9) are all about how cost scales. A better growth rate beats faster hardware, and some problems resist every known shortcut.

Engineering with asymmetry

Caches, error-correcting codes, cryptography and learning (ideas 8, 10–12) turn an imbalance into an advantage: fast over slow, a little redundancy over a lot of noise, easy-to-do over hard-to-undo, and many examples over hand-written rules.

Further reading

  • Charles Petzold, Code: The Hidden Language of Computer Hardware and Software (2nd ed., 2022). From switches and binary to a working computer.
  • W. Daniel Hillis, The Pattern on the Stone (1998). A short tour of how computers work, by a supercomputer designer.
  • John MacCormick, Nine Algorithms That Changed the Future (2012). Search engines, compression, error correction and public-key cryptography for general readers.
  • Lance Fortnow, The Golden Ticket (2013). P vs. NP and why it matters.
  • James Gleick, The Information (2011). A history of information theory and the people behind it.
  • Brian Christian & Tom Griffiths, Algorithms to Live By (2016). Caching, scheduling and search applied to everyday decisions.