Amortised analysis
After thiswhat you will be able to doShow that doubling a dynamic array keeps the total cost of n additions below 3n, and distinguish that amortised guarantee from the cost of any single addition.
Questionwhat this lesson answersAdding an item to a growing array is usually cheap, but now and then the array is full and every item must be copied to a bigger block, which costs n. So how can adding an item be called constant time when some additions cost n, and what does it mean to average over a sequence of operations rather than over inputs?
Not coveredwhat this lesson leaves outWe analyse one structure, the array that doubles when full, by two methods that agree. We do not survey other amortised structures, and we keep this separate from the average over inputs that the expectation lesson built.
Adding an item to an array looks harmless until the space runs out. An array keeps items next to each other in one block of storage. If that arrangement can hold more items than it started with by moving its contents to a larger block, it is called a dynamic array. The number of items the current block can hold is its capacity. As long as there is an empty place, an addition only places the new item there. That placement is called a write, and it costs one unit of work in this model.
The trouble arrives when the block is full. Adding one more item first asks for a larger block, then copies every old item across, then writes the new one. If there are stored items, that copy can cost about units. Most additions cost one. A few cost an amount that grows with the array. How can the usual claim that adding to a dynamic array is constant time survive that fact?
Set one exact rule before counting. Start with room for one item. Whenever the current block is full, make the next block twice as large. The capacity therefore doubles at sizes , , , , and so on. Those are the numbers reached by repeatedly multiplying by two, called powers of two. The costly addition is the one that arrives just after one of those blocks has filled. As the array grows, the gaps between those full blocks get wider, so the costly additions become rarer.
Count the whole run
One way to answer the puzzle is to add every write and copy in the entire run, then divide the total by the number of additions. This whole-run calculation is called the aggregate method. The writes cost . Copies happen only when the capacity doubles: first one item, then two, then four, and so on, stopping before the copied block reaches items.
The copy amounts form a finite sum whose next number is twice the previous one. A sum with that repeated multiplication is called a geometric sum. Such a sum is always one less than twice its last term, because each term equals all the earlier terms plus one: is , one short of the next block of . Since the last copied block holds fewer than items, the copy total is below twice the number of additions:
For a run whose number of additions is a power of two, the last copied block has half that many items, so the same sum has an exact value:
The loose bound is enough for every run. There are ordinary writes and fewer than copies, so the total stays below three times the number of additions:
Divide that worst-case total by the number of additions:
The resulting per-addition average over one whole sequence is the amortised cost. It does not use a probability, and it does not need a distribution. It says that every run of additions has a total cost that can be shared among its operations, even when the particular run contains an expensive copy.
Put spare work in a bank
There is a second way to reach the same bound. Instead of adding the final bill and sharing it at the end, charge every addition a fixed price that is higher than a single write, and save the overpayment for later. This running ledger is the accounting method, also called the banker’s method. One unit of work paid in advance and held for a later copy is a credit.
Charge each addition units. One pays for its write. The other units become credits in the bank. Cheap additions make the balance rise. A doubling spends credits to copy the full old block, so the balance dips. The cheap additions since the last doubling make new deposits, and any credit not spent at an earlier doubling carries forward with them. Together they cover the next copy.
The aggregate result already proves that this bank cannot run dry. The first few additions of a run are themselves a shorter run, so the same bound applies at every point along the way: after any number of additions, the actual work is less than three times that many additions. The difference is the bank balance:
So the balance never becomes negative. Charging was enough, which gives an amortised cost of at most . The island traces that balance after every addition. Its marked dips are the times a full block is copied.
Most additions are ordinary writes
At eight additions, most points are ordinary writes. The marked points are the full blocks that had to copy their contents before the new item could fit.
Charge three units per addition
Saved work covers the rare copying spikes
The trace records the banker's balance after every addition. A marker means that this addition copied existing items. In the doubling view, each dip stays above the zero line.
- bank balance after each addition
- copy event
The gaps between copy markers widen because a larger block takes longer to fill.
- Additions so far
- 8
- Total cost
- 15
- Amortised cost, total divided by n
- 1.875
- Current balance
- 9
doubling capacity after 8 additions: total cost 15, amortised cost 1.875 per addition, and current bank balance 9. The balance stayed non-negative under a charge of 3 per addition.
An average with no probability
This average is over a sequence of operations, in the worst case, with no probability anywhere. The Expectation door below answers a different question. There, an average was taken over inputs and depended on a chosen distribution. Here, no input is given extra weight. Both results are loosely called averages, but confusing them changes the claim being made.
The What we agree to throw away door names the final move. The number is a constant, so an amortised cost bounded by it is . The notation discards the particular constant just as it has throughout the arc. It does not say that every addition costs one. A single addition can still cost work in the worst case. Amortised is a promise about any run of additions together, not about each addition on its own.
Why doubling is the whole point
It may seem strange to discard the constant that made the accounting work. But repeated multiplication by two, called geometric growth, is what makes the copies rare enough that their total is a constant amount per addition. The constant is later thrown away by Big O, while the doubling rule is the reason there was a constant to throw away.
If the array grew by one slot instead, each later addition would copy one more old item than the last. The copies would make the triangular number from Summing a loop:
Including the writes makes the average cost per addition this:
That is about half of , a linear amount, not a constant one. Doubling is not an incidental implementation detail. It is exactly what turns occasional copying into a constant amortised cost.
Doorswhat to read next, and why
- ExpectationThat lesson averaged a cost over inputs using a chosen distribution. This lesson averages over a sequence of operations with no probability at all. The two averages answer different questions and should not be confused.
- What we agree to throw awayThe amortised cost here comes out as a small constant number of operations per addition. Calling that constant time O(1) drops the constant, the same discarding move the arc has used throughout.
- Summing a loopThe total copying cost is the sum one plus two plus four and so on. That geometric sum, like the triangular one counted there, is what makes the whole sequence cheap.
Symbolswhat each one means, and whether we defined it, measured it, or just started there
- nStatus: defined
- the number of additions made to the array, one after another
- the capacityStatus: defined
- how many items the current block of storage can hold before it must grow
- the amortised costStatus: defined
- the total cost of a whole sequence of operations divided by the number of operations, the average this lesson defines
- a creditStatus: defined
- a unit of work paid in advance on a cheap operation and saved to spend on a later expensive one
- one unit of workStatus: bottoms out
- the cost of a single write or a single copy, the primitive this lesson counts and does not break down further
What these classifications mean
- defined
- circular by construction, true because we chose it
- empirical
- a measured claim about the world that could have come out otherwise
- bottoms out
- a primitive of the model, with nothing under it here
- door
- used here, explained elsewhere