Data Structures and Algorithms
with Object-Oriented Design Patterns in C# |

The running times calculated for the various
operations of the two ordered list implementations,
`OrderedListAsArray` and `OrderedListAsLinkedList`,
are summarized below in Table .
With the exception of two operations,
the running times of the two implementations
are asymptotically identical.

ordered list implementation | |||

| OrderedList- | OrderedList- | |

method | AsArray | AsLinkedList | |

Insert | O(1) | O(1) | |

IsMember | O(n) | O(n) | |

Find | O(n) | O(n) | |

Withdraw | O(n) | O(n) | |

this[int]{get} | O(1) | O(n) | |

FindPosition | O(n) | O(n) | |

Cursor.Datum{get} | O(1) | O(1) | |

Cursor.InsertAfter | O(n) | O(1) | |

Cursor.InsertBefore | O(n) | O(n) | |

Cursor.Withdraw | O(n) | O(n) |

The two differences are the indexer
and the `InsertAfter` method.
The indexing operation can be done constant time when
using an array,
but it requires *O*(*n*) in a linked list.
Conversely, `InsertAfter` requires *O*(*n*) time when using
an array,
but can be done in constant time in the singly-linked list.

Table does not tell the whole story.
The other important difference between the two implementations
is the amount of space required.
Consider first the array implementation, `OrderedListAsArray`.
The storage required for an array was discussed in Chapter .
Using that result, the storage needed for an `OrderedListAsArray`
which can hold *at most* *M* `ComparableObject`s is given by:

Notice that we do not include in this calculation that space required for the objects themselves. Since we cannot know the types of the contained objects, we cannot calculate the space required by those objects.

A similar calculation can also be done
for the `OrderedListAsLinkedList` class.
In this case, we assume that the actual number of contained objects is *n*.
The total storage required is given by:

If we assume that integers and object references require four bytes each,
the storage requirement for the `OrderedListAsArray` class
becomes 12+4*M* bytes;
and for the `ListAsList` class, 16+12*n* bytes.
That is, the storage needed for the array implementation is *O*(*M*),
where *M* is the maximum length of the ordered list;
whereas, the storage needed for the linked list implementation is *O*(*n*),
where *n* is the actual number of items in the ordered list.
Equating the two expressions,
we get that the break-even point occurs at *n*=(*M*-1)/3.
That is, if *n**<*(*M*-1)/3,
the array version uses more memory space;
and for *n**>*(*M*-1)/3, the linked list version uses more memory space.

It is not just the amount of memory space used that should be considered
when choosing an ordered list implementation.
We must also consider the implications of the existence of the limit *M*.
The array implementation requires *a priori* knowledge
about the maximum number of items to be put in the ordered list.
The total amount of storage then remains constant during the course
of execution.
On the other hand, the linked list version has no pre-determined maximum length.
It is only constrained by the total amount of memory available to the program.
Furthermore, the amount of memory used by the linked list version varies
during the course of execution.
We do not have to commit a large chunk of memory
for the duration of the program.

Copyright © 2001 by Bruno R. Preiss, P.Eng. All rights reserved.