Assuming your analysis is correct and the operations are O(log(n))
per access and O(n)
the first time...
If you always access the bottommost element (using some kind of worst-case oracle), a sequence of a
accesses will take O(a*log(n) + n)
. And thus the amortized cost per operation is O((a*log(n) + n)/a)
=O(log(n) + n/a)
or just O(log(n))
as the number of accesses grows large.
This is the definition of asymptotic average-case performance/time/space, also called "amortized performance/time/space". You are accidentally thinking that a single O(n)
step means all steps are at least O(n)
; one such step is only a constant amount of work in the long run; the O(...)
is hiding what's really going on, which is taking the limit of [total amount of work]
/[queries]
=[average ("amortized") work per query]
.
This will never be less than O(log n).
It has to be in order to get O(log n)
average performance. To get intuition, the following website may be good: http://users.informatik.uni-halle.de/~jopsi/dinf504/chap4.shtml specifically the image http://users.informatik.uni-halle.de/~jopsi/dinf504/splay_example.gif -- it seems that while performing the O(n)
operations, you move the path you searched scrunching it towards the top of the tree. You probably only have a finite number of such O(n)
operations to perform until the entire tree is balanced.
Here's another way to think about it:
Consider an unbalanced binary search tree. You can spend O(n)
time balancing it. Assuming you don't add elements to it*, it takes O(log(n))
amortized time per query to fetch an element. The balancing setup cost is included in the amortized cost because it is effectively a constant which, as demonstrated in the equations in the answer, disappears (is dwarfed) by the infinite amount of work you are doing. (*if you do add elements to it, you need a self-balancing binary search tree, one of which is a splay tree)