With no additional data structures / constant space restriction:
The O(n2)
algorithm you described is essentially selection sort.
If you have access to an iterator of some kind (if not, how else would you access elements in the collection?), I believe one can do better by using a custom merge-sort as follows:
Compare element 1 and 2. removeAndAppend
the smaller one, then removeAndAppend
the remaining one. Do the same for element 3 and 4, 5 and 6, ... and element n-1 and n.
Now you'll have sorted subcollections of 2 elements each.
Merge indices (1,2) and (3,4). To do this, have 2 iterators starting from the beginning. Start by incrementing the one twice. Then proceed to do a merge-sort as usual using the removeAndAppend
function. Do the same for (5,6) and (7,8), (9,10) and (11,12), ... and (n-3,n-2) and (n-1,n).
Now you'll have sorted subcollections of 4 elements each.
Merge size 4 collections similar to above, then 8, 16, 32, etc., until you reach the collection size.
The whole process will look something like this:
// setSize is how large sets we're currently merging
for setSize = 1; setSize <= n/2; setSize *= 2
iterator left = begin
right = begin
for pos = 1 to n/(2*setSize)
// here right and left are both at the beginning
// even after the previous iteration of the loop,
// since we've removed and appended all other elements
// so we only need to increase right by setSize
right += setSize
for i = 1 to 2*setSize
if (left.value <= right.value)
removeAndAppend(left)
else
removeAndAppend(right)
The above is just a basic draft, it might not be 100% correct and doesn't account for when the collection isn't a power of 2 (which will happen often). You need to be careful in this case otherwise you might wrap around, or not go far enough and end up with a partially sorted collection.
The complexity analysis should be almost identical to regular merge-sort and result in an O(n log n)
running time.
With additional data structures / no constant space restriction:
Extract all the elements into another collection, sort this in O(n log n)
(using a sorting algorithm of your choice) and iterate through the sorted set, calling removeAndAppend
on the original collection for each.
If you're not allowed to extract elements, this method can still be used by having a collection of indices instead and, to do a compare, simply look up the applicable elements. However, for this to be efficient, you'll need constant time lookup by index.