Back to index

CSC 378F Data Structures and Algorithm Analysis

AMORTIZED ANALYSIS
[CLR 18] 
To 'amortize' means to pay off over time.

Consider a sequence aa_1.gif of operations aa_2.gif
e.g. aa_3.gif is ins, del, or find in a BST.
 

If T( aa_4.gifaa_5.gif O( f( n ) )
Then aa_6.gif aa_7.gif O( M f( n ) )
But is this the tightest bound?
Queue Example
A FIFO queue supportsEnqueue( k )andaa_8.gif Dequeue,
implemented with two stacks :
example

Enqueue order : 1, 2, 3, 4, 5Dequeue order : 1, 2, 3, 4, 5

Note that -
T( Enq ) aa_9.gif O( 1 )T( Deq ) aa_10.gif O( n ), for n item in the queue

Let aa_11.gifaa_12.gif

What is T( aa_13.gif )?Clearly, O( aa_14.gif )

Intuition
- Each element is pushed once, transferred once, and popped once.
- So . . . T( aa_15.gif ) is proportional to the number of elements that pass through the queue.
- So . . . T( aa_16.gifaa_17.gif O( M )
Let aa_18.gif be a sequence of operations.

Define the amortized time complexityaa_19.gif , of operation aa_20.gif to be any function that satisfies

 
aa_21.gif 
 
The Amortization Property
aa_22.gif is usually chosen as the 'smallest' function satisfying this property.
Intuition
For any prefix of the sequence, the sum of the amortized costs is an upper bound on the true cost.
Intuition
aa_23.gif is the "average cost" of aa_24.gif in the context of the set aa_25.gif


The Guessing Method
Since each element is pushed, transferred, and popped, we will "charge" each element for 3 time units when it is enqueued. Each time unit pays for one of push, transfer, or pop.

Then aa_26.gif ( Enq ) = 3. Since Dequeue uses only transfer and pop, which have already been 'charged for', aa_27.gif ( Deq ) = 0. Note that the functions, and their costs, are arbitrary and specific to this example.

Do these amortized times satisfy the
amortization property?

Yes!

Proof by Induction
Suppose it's true for k-1 operations : aa_28.gif

If aa_29.gif = Enq, then -

aa_30.gif

 aa_31.gif

 aa_32.gif

 aa_33.gif

If aa_34.gif = Deq, then let -
e be the number of Enq in aa_35.gif ,
s be the size of S,
t be the size of T. Then -

aa_36.gif

 aa_37.gif ( # push + # xfer + # pop ) + T( aa_38.gif )

 aa_39.gif ( e + ( e - s ) + ( e - s - t ) ) + T( aa_40.gif )

 aa_41.gif ( 3e - 2s - t ) + ( 1 + s )

 aa_42.gif 3e + 1 - ( s + t )

 aa_43.gif 3esince s + t aa_44.gif 1 ( i.e. queue not empty )

 aa_45.gif

 aa_46.gif 

Therefore, if we choose
 aa_47.gif  aa_48.gif

then we've proven that
 aa_49.gif

and "the sum of the amortized costs is an upper bound on the actual cost."

 aa_50.gif
 aa_51.gif O( M )
which is a better (tighter) bound than our earlier O( aa_52.gif )

But this, you may agree, is cumbersome. Here's an easier way . . .



Accounting Method
Let each piece of data 'store' some (virtual) time credits. Each time credit 'pays for' a bounded-time operation on the piece of data. Operations are not charged if they use existing credits.
 
aa_53.gif 
 
Does this satisfy the property?
aa_54.gif

 aa_55.gif

 aa_56.gif

 aa_57.gif

i.e. We can't use credits that we've not stored!


Queue Example Revisited
- Store two credits on an item when enqueing it.
- Use one when transferring.
- Use one when popping.
aa_58.gif

=1 + 2 + 0=3

aa_59.gif
( suppose aa_60.gif transfers s items )

= ( s + 1 ) + 0 - ( s + 1 )where 's' : xfer and '1' : pop

= 0

Is aa_61.gif ?

Yes, since there are always 2 credits on items in S and 1 credit on items in T.

Back to index