"logo.gif"  
Main
Read Online
Download PDF
Additional resources
Revision history
Known typos/bugs
Report a bug
License terms
About the author
"node525_1.gif" "node525_2.gif" "node525_3.gif"

5.5.2.8   Example:   linked lists and the fast accumulation of results

For many applications, one needs to be able to build up a list of some intermediate results obtained in some computation. The easiest way to set up such a list is to use Append or Prepend (or perhaps, AppendTo or PrependTo). However, for large lists this method is quite inefficient. The reason is that lists in Mathematica are implemented as arrays, and thus every time we add an element, the entire list is copied.

We can use FoldList to illustrate the creation of a list in such manner :

"node525_4.gif"

"node525_5.gif"

"node525_6.gif"

"node525_7.gif"

Now, let us do some performance tests :

"node525_8.gif"

"node525_9.gif"

"node525_10.gif"

"node525_11.gif"

"node525_12.gif"

"node525_13.gif"

"node525_14.gif"

"node525_15.gif"

"node525_16.gif"

"node525_17.gif"

We see that  the time used by this operation is quadratic in the size of the list. We of course would like a linear time. One way to achieve this which is available starting with the Mathematica  version 5.0 is to use the Reap-Sow technique (to be described in Part II). Another (perhaps, slightly less efficient) way to get a linear time is to use linked lists. We will follow the discussion in the book of David Wagner [7].

"node525_18.gif"

A linked list in Mathematica is a structure of the type

"node525_19.gif"

The advantage of this representation is that on every level, we have a list containing just 2 elements, which is easy to copy. It will not work in this way for elements that are lists themselves, but then one can replace a list by an arbitrary head <h>.

"node525_20.gif"

"node525_21.gif"

To avoid a possible conflict with some < h > already defined, we can use Module[{h}, ...] to make it local.

Using Fold is the most natural way to  create such structures :

"node525_22.gif"

"node525_23.gif"

"node525_24.gif"

"node525_25.gif"

Converting them back to a normal list is just as easy with Flatten :

"node525_26.gif"

"node525_27.gif"

"node525_28.gif"

"node525_29.gif"

Notice that in the second case we used the fact that Flatten  takes as an optional third argument the head which has to be Flatten - ed, and then Flatten - s only subexpressions with this head. In any case, this is another linear-time operation.

We can now write a function:

"node525_30.gif"

Let us do some performance tests:

"node525_31.gif"

"node525_32.gif"

"node525_33.gif"

"node525_34.gif"

"node525_35.gif"

"node525_36.gif"

We see that the time is roughly linear in the list size, and for example, for a list of 20000 we get already a speed - up of the order of 100 times! Flattening is even faster:

"node525_37.gif"

"node525_38.gif"

Here we assumed that the list of results is accumulated immediately, just to separate this topic from the other problem - specific part of a program.   If the list is accumulated not immediately but some other operations are performed in between (which is what usually happens), one just has to use the idiom list  = {newelement, list}, to achieve the same result.

"node525_39.gif" "node525_40.gif" "node525_41.gif"

Created by Wolfram Mathematica 6.0  (05 February 2009) Valid XHTML 1.1!