Some Notes on Sorting Algorithms...
Big O Complexity Cheat Sheet
http://bigocheatsheet.com/
Comparator Interface
When comparing two objects we'll be using the Comparator interface:
http://docs.oracle.com/javase/7/docs/api/java/util/Comparator.html
Comparator takes two arguments: left and right. Implementation is typically:
left < right = -1
left > right = 1
left = right = 0
String implements the Comparable interface and the examples below use Strings.
http://docs.oracle.com/javase/7/docs/api/java/lang/String.html
So you can compare strings like this:
String s1 = "A";
String s2 = "B";
s1.compareTo(s2);
A < B = -1
A > B = 1
A = B = 0
This could be more generic than using Strings but using a particular data type makes the examples shorter for the moment. 
Terminology
Stability: When two items with the same value stay in the same relative position after sort
In Place:  Whether or not algorithm uses separate data structure to sort
Bubble Sort
Implementation:
- start at the beginning of the list
- compare the first and second items
- if the first is bigger than the second, swap
- repeat with each subsequent pair until end of list
- biggest item will be at the bottom
- start again at the beginning of the list and skip the last item as already sorted
- continue starting over at beginning of list and skipping already sorted items until all items sorted
Sample Code: 
package com.radicalsoftware.example.sort;
import java.util.ArrayList;
import java.util.List;
public class BubbleSort {
    public static void main(String[] args) {
       
        ArrayList<String> list = new ArrayList<String>();        
        list.add("Zero");
        list.add("Alpha");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
        sort(list);
       
        for (String s: list){
            System.out.println(s);
        }
    
    }
   
    public static List<String> sort(List<String> list){
       
        assert list != null : "list cannot be null";
       
        int size = list.size();
       
        for (int pass = 1; pass < size; ++pass){
            for (int left = 0; left < (size - pass); ++left){
                int right = left + 1;
                if (list.get(left).compareTo(list.get(right)) > 0){
                    swap(list, left, right);
                }
            }
        }
       
        return list;
       
    }
   
    private static <T> void swap(List<T> list, int left, int right){
        T obj = list.get(left);
        list.set(left,  list.get(right));
        list.set(right, obj);
    }
   
}
Selection Sort
- similar to sorting books on a book shelf 
- unstable 
- for each spot in the list 
- scan all items in list to find the smallest (or largest) item
- put the smallest (or largest) item in that spot
- move to the next spot and repeat skipping already sorted items
Sample Code:
package com.radicalsoftware.sort;
import java.util.ArrayList;
import java.util.List;
public class SelectionSort {
    public static void main(String[] args) {
        
        ArrayList<String> list = new ArrayList<String>();
        list.add("Zero");
        list.add("Alpha");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
        sort(list);
        
        for (String s: list){
            System.out.println(s);
        }
        
    
    }
    
    public static List<String> sort(List<String> list){
        
        assert list != null : "list cannot be null";
        
        int size = list.size();
        
        for (int slot = 0; slot < size-1; ++slot){
            
            int smallest = slot;
            
            //find the smallest in remaining items
            for (int checkSlot = slot + 1; checkSlot < size; ++checkSlot){
                if (list.get(slot).compareTo(list.get(checkSlot)) > 0){
                    smallest = checkSlot;
                    break;
                }
            }
            
            //if smallest does not equal current slot then swap
            if (smallest != slot)
                swap(list, smallest, slot);
        }
        
        return list;
        
    }
    
    private static <T> void swap(List<T> list, int left, int right){
        
        T obj = list.get(left);
        list.set(left,  list.get(right));
        list.set(right, obj);
    
    }
}
Insertion Sort
- similar to sorting cards where you sort all the numbers within each suit
- create a new list and insert items into it
- use an iterator instead of an index
- insert the first item into the list
- use linked list so can scan and insert each item into correct relative location
Sample Code: 
package com.radicalsoftware.sort;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
public class InsertionSort {
    public static void main(String[] args) {
       
        ArrayList<String> list = new ArrayList<String>();
       
        list.add("Zero");
        list.add("Alpha");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
       
        List<String> sortedList = sort(list);
       
        for (String s: sortedList){
            System.out.println(s);
        }
       
    
    }
    
    public static List<String> sort(List<String> list){
       
        assert list != null : "list cannot be null";
       
        final List<String> sortedList = new LinkedList<String>();
       
        for (String s: list){
    
            int slot = sortedList.size();
       
            while (slot > 0){
                if (s.compareTo(sortedList.get(slot - 1)) >= 0){
                    break;
                }
                --slot;
            }
           
           
            sortedList.add(slot, s);
        }
       
       
        return sortedList;
       
    }
    
} 
Shell Sort
- breaks large lists into smaller lists
- based on concept of H-sorting - every Hth item is sorted relative to other items
- not stable 
Sample Code: 
package com.radicalsoftware.sort;
import java.util.ArrayList;
import java.util.List;
public class ShellSort {
    private static final int[] _increments = {1, 3, 5, 7, 11, 20};
    
    public static void main(String[] args) {
        
        ArrayList<String> list = new ArrayList<String>();
        
        list.add("Zero");
        list.add("Alpha");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
        list.add("Money");
        list.add("Food");
        list.add("Stars");
        list.add("Moon");
        sort(list);
        
        for (String s: list){
            System.out.println(s);
        }
        
    
    }
    
    public static List<String> sort(List<String> list){
        
        assert list != null : "list cannot be null";
        
        for (int i = 0; i < _increments.length; i++){
            int increment = _increments[i];
            if (list.size() < increment * 2)
                break;
            hSort(list, increment);
        }
        
        return list;
        
    }
    
    private static void hSort(List<String> list, int increment){
        for (int startIndex = 0; startIndex < increment; ++startIndex){
            for (int i = startIndex + increment; i < list.size(); i += increment){
                
                String value = list.get(i);
                
                int j;
                
                for (j = i; j > startIndex; j -= increment){
                    
                    String previousValue = list.get(j - increment);
                    
                    if (value.compareTo(previousValue) >=0)
                        break;
                    
                    list.set(j, previousValue);
                    
                }
                
                list.set(j, value);
                
            }
        }
    }
    
}
Quick Sort
- uses recursion
- does the work first, then the recursion 
- divide and conquer, recursively sorting smaller parts of list
- place an item in final position, smaller items left, larger items right
- divided into two parts (not necessarily two halves)
- not stable
- use quick sort until length of list is 10 or less and then use insertion sort 
Best case: O(n Log(n)) -- partition element is middle element
Worst Case: O(n2) -- completely unbalanced
Implementation
- Choose partition item (last, mean of first, last and middle, etc.)
- indexes start at beginning and end (less the partition item) and advance towards each other
- left index stops when finds item larger than partitioning item
- right index stops when finds item smaller than partitioning item
- when both stop swap items 
- point where indexes meet - insert partitioning item
- then sort the sublists to the right and left of the partitioning item
Sample Code:
package com.radicalsoftware.sort;
import java.util.ArrayList;
import java.util.List;
public class QuickSort {
    public static void main(String[] args) {
       
        ArrayList<String> list = new ArrayList<String>();
        list.add("Alpha");
        list.add("Zero");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
        sort(list);
       
        for (String s: list){
            System.out.println(s);
        }
       
    
    }
    
    public static void sort(List<String> list){
       
        assert list != null : "list cannot be null";
       
        quicksort(list, 0, list.size()-1);
       
    }
    
    public static void quicksort(List<String> list, int startIndex, int endIndex){
       
        if (startIndex < 0 || endIndex >= list.size())
            return;
       
        if (endIndex <= startIndex)
            return;
       
        String value = list.get(endIndex);
       
        int partition = partition(list, value, startIndex, endIndex -1);
       
        if (list.get(partition).compareTo(value) < 0)
            ++partition;
       
        if (partition != endIndex)
            swap(list, partition, endIndex);
       
        //sort right and left of partition
        quicksort(list, startIndex, partition -1);
        quicksort(list, partition + 1, endIndex);
       
    }
    
    private static int partition(List<String> list, String value,
            int leftIndex, int rightIndex) {
        int left = leftIndex;
        int right = rightIndex;
       
        while (left < right){
           
            if(list.get(left).compareTo(value)< 0){
                ++left;
                continue;
            }
    
            if(list.get(right).compareTo(value)>=0){
                --right;
                continue;
            }
           
            swap(list, left, right);
            ++left;
        }
    
        return left;
    }
    private static void swap(List<String> list, int left, int right){
        String obj = list.get(left);
        list.set(left,  list.get(right));
        list.set(right,  obj);
    }
} 
Merge Sort
- not in place
Implementation:
- divide the list in half recursively until you get to one item arrays
- merge each array together two at a time
-- pointer at the beginning of each two array merging
-- compare elements and put the smaller into a new array
-- move pointer of array you took element from +1
-- repeat for all elements
-- repeat for all arrays
package com.radicalsoftware.sort;
import java.util.ArrayList;
import java.util.List;
public class MergeSort {
    public static void main(String[] args) {
       
        ArrayList<String> list = new ArrayList<String>();
       
        list.add("Zero");
        list.add("Alpha");
        list.add("Cat");
        list.add("Boy");
        list.add("Dog");
        list.add("Rose");
        list.add("Lion");
        list.add("Fire");
        list.add("Dragon");
        list.add("Math");
        list.add("Logic");
        list.add("Salmon");
    
        List<String> sortedList = sort(list);
        for (String s: sortedList){
            System.out.println(s);
        }
    }
    
    public static List<String> sort(List<String> list){
       
        assert list != null : "list cannot be null";
       
        return mergesort(list, 0, list.size()-1);
       
    }
    private static List<String> mergesort(List<String> list, int startIndex, 
        int endIndex) {
       
       
        int middleIndex = (startIndex + endIndex)/2;
       
        if (startIndex < endIndex){
           
            List<String> left = mergesort(list, startIndex, middleIndex);
            List<String> right = mergesort(list, middleIndex + 1, endIndex);
           
            return merge(left, right);
       
        }
       
        List<String> mergedList = new ArrayList<String>();
        mergedList.add(list.get(startIndex));       
        return mergedList;
       
       
       
    }
    private static List<String> merge(List<String> left, List<String> right) {
       
        List<String> mergedList = new ArrayList<String>();
       
        int rightIndex = 0;
        int leftIndex = 0;
       
        while(leftIndex < left.size() || rightIndex < right.size()){
            boolean rightHasMore = rightIndex < right.size();
            boolean leftHasMore = leftIndex < left.size();
           
            if (!rightHasMore || 
                (leftHasMore && 
                left.get(leftIndex).compareTo(right.get(rightIndex)) <= 0)){
                mergedList.add(left.get(leftIndex));
                leftIndex++;
            }else{
                if(rightHasMore){
                    mergedList.add(right.get(rightIndex));
                    rightIndex++;
                }
            }   
       
           
        }
           
        return mergedList;
    }
    
} 
Heap Sort
- in place (uses less memory than mergesort which has to allocate additional storage)
- comparison based sort
- selection sort family
- slower than well implemented quick sort, but better worst case
- in place
- not stable
Implementation
An array viewed as a nearly complete binary tree (meaning a subsequent level is not started until the previous level is completely filled).
http://www.youtube.com/watch?v=B7hVxCmfPtM 
  
Bucket, counting and radix sort:
http://www.youtube.com/watch?v=woTbZMli6z4 
 Bucket Sort
- stable sort
- range of keys can't be too big
- linear time
Counting Sort 
- stable sort
- range of keys can't be too big
- linear time
Implementation:
- histogram
- indicies
- place 
Radix sort
- stable
- only good when
- use counting sort trick on the least significant digit
- not in place 
- linear time
- unlimited number of keys
- uses the stability of bucket sort and counting sort 
