A wonderful series of Debug Podcasts where the guest @NitinGanatra, former iOS Apps Director at Apple, speaks about the evolution of the products over the years from a technical insiders perspective. Very enjoyable and eye openning 6 hours of Apple geek goodness…

Introsort or introspective sort is a hybrid sorting algorithm that provides both fast average performance and (asymptotically) optimal worst-case performance. It begins with quicksort and switches to heapsort when the recursion depth exceeds a level based on (the logarithm of) the number of elements being sorted. This combines the good parts of both algorithms, with practical performance comparable to quicksort on typical data sets and worst-case O(n log n) runtime due to the heap sort. Since both algorithms it uses are comparison sorts, it too is a comparison sort.

Introsort was invented by David Musser in Musser (1997), in which he also introduced introselect, a hybrid selection algorithm based on quickselect (a variant of quicksort), which falls back to median of medians and thus provides worst-case linear complexity, which is optimal. Both algorithms were introduced with the purpose of providing generic algorithms for the C++ Standard Library which had both fast average performance and optimal worst-case performance, thus allowing the performance requirements to be tightened.

This implementation performs an unstable sort; that is, if two elements are equal, their order might not be preserved. In contrast, a stable sort preserves the order of elements that are equal.

For arrays that are sorted by using the Heapsort and Quicksort algorithms, in the worst case, this method is an O(_{n} log _{n}) operation, where _{n} is the Length of array.

You can view the full source for .NET 4.5 sorting implementation here: .NET 4.5.1 QuickSort

Quicksort, also known as partition-exchange sort, uses these steps.

Choose any element of the array to be the pivot.

Divide all other elements (except the pivot) into two partitions.
- All elements less than the pivot must be in the first partition.
- All elements greater than the pivot must be in the second partition.

Use recursion to sort both partitions.

Join the first sorted partition, the pivot, and the second sorted partition.

voidswap(int*a,int*b){intt=*a;*a=*b;*b=t;}voidsort(intarr[],intbeg,intend){if(end>beg+1){intpiv=arr[beg],l=beg+1,r=end;while(l<r){if(arr[l]<=piv)l++;elseswap(&arr[l],&arr[--r]);}// swapping elements within the array // to avoid the memory allocation of more arrays.swap(&arr[--l],&arr[beg]);sort(arr,beg,l);sort(arr,r,end);}}

You start with an unordered sequence.
You create N empty queues.
You loop over every item to be sorted.
On each loop iteration, you look at the last element in the key.
You move that item into the end of the queue which corresponds to that element.
When you are finished looping you concatenate all the queues together into another sequence.
You then reapply the procedure described but look at the second last element in the key.
You keep doing this until you have looped over every key.
When you complete this process the resulting sequence will be sorted as described above.

Let n_{i} be the number of items in the sequence to be sorted. N is number of integers that each key element can take. Let n_{k} be the number of keys in each item.

The total time to sort the sequence is thus O(n_{k}(n_{i} + N)).

functionmergesort(list){if(list.length<=1)returnlist;varmid=Math.floor(list.length/2),left=list.slice(0,mid),right=list.slice(mid,list.length);returnmerge(mergesort(left),mergesort(right))}functionmerge(left,right){varsorted=[];while(left&&left.length>0&&right&&right.length>0){varb=left[0]<=right[0];sorted.push(b?left[0]:right[0]);// remove the element which was added to the sorted arrayb?left.splice(0,1):right.splice(0,1);}returnsorted.concat(left,right);}