log(n) amortized growth for containers

Andrei Alexandrescu via Digitalmars-d digitalmars-d at puremagic.com
Thu Dec 10 19:55:27 PST 2015


Many thanks to Jason Causey and Jakob Ovrum for their work on heaps and 
Randomized Slide to Front.

Here's a quick thought on growth schedule for arrays. The classic 
approach is to grow by a geometric schedule. For example: 1, 2, 4, 8, 
16, etc. That way, n memory moves are necessary for achieving a capacity 
equal to n, so on average we spend a constant amount of time per 
appended element.

The main disadvantage with this growth schedule is there are on average 
n/2 slack memory slots. Also, a growth factor of 2 is unfriendly to the 
memory allocator (long discussion) so a smaller one (such as the golden 
cut or less) would be better.

Anyhow, I was thinking why O(1) amortized growth and not O(log n)? The 
latter is considered scalable all right and the hope is to get a 
corresponding reduction in the slack memory space.

To figure a growth schedule that leads to log(n) work per element, a 
differential equation must be solved:

s(n) / s'(n) = log(x)

where s(n) will be the (continuous extension of the) growth schedule's 
sum, i.e. s(n) = f(1) + f(2) + ... + f(n). In other word, s(n) is how 
many elements we moved around, and s'(n) is the capacity after n steps. 
The division gives us how much work was done per element.

To verify, if s(n) = n, you get O(n) work per element, i.e. quadratic 
behavior for linear capacity growth. If s(n) = 2^n, you get O(1) work 
per element.

So I entered the equation above in Wolfram:

https://www.wolframalpha.com/input/?i=y%28x%29+%2F+y%27%28x%29+%3D+log%28x%29

So the growth schedule is exponential of the LogIntegral(n). Let's write 
it as:

f(n) = 2^^li(n)

Not too nice, but easy to tabulate for the relevant ranges. Let's take a 
look at the slack space at capacity f(n):

slack(f(n)) = f(n) - f(n - 1)

Sadly the expression doesn't seem to simplify and I couldn't find a good 
online plotter that can plot 2^^li(x). Here's what Mathematica free shows:

https://www.wolframalpha.com/input/?i=2%5Eli%28x%29+-+2%5Eli%28x+-+1%29

Compare with:

https://www.wolframalpha.com/input/?i=2%5Ex+-+2%5E%28x+-+1%29

The slack elements seem to grow considerably slower, which is great.

Does anyone know of a plotter that supports logarithmic integral? Of 
course better ideas about all of the above are welcome!


Thanks,

Andrei


More information about the Digitalmars-d mailing list