James said:
the most common
solution seems to be to take the median of the first, last and
middle values, and getting the middle value requires true random
access.
Actually it doesn't. It's actually possible to apply
median-of-three-pivot quicksort to a linked list even without random access.
Ok, with the very first partitioning it cannot be done. The very first
partition must be done in the basic way (eg. taking the first value as
pivot). However, all subsequent partitionings can be performed with the
pivot chosen with the median-of-three method.
The way to do this is quite simple: While partitioning, ie. when
traversing the list forwards and backwards, keep an iterator which
always points to the middle element of the lower partition (ie. you
advance it once for every two advances of the traversal) and another
which points to the middle element of the upper partition. After you
have partitioned like this, you have all the necessary iterators to
calculate the new two median-of-three elements and recursively partition
the two parts.
Even optimizing this quicksorting with insertion sort when the
partition is small enough is possible (because while partitioning you
can count the size of each subpartition).
The usual solution I've seen for sorting linked lists is
mergesort, which can be very fast *if* you don't have to
actually copy values (which you don't if you're dealing with
linked nodes).
That's true. Merge sort with doubly-linked lists can be very fast
because no extra memory is required (unlike when merge-sorting arrays).
(Basically all the extra memory required to perform merge sort is
already there, in the two links in each element.)