Sorting Algorithms


1. Sorting Arrays of Arbitray Element Type

// another application/client program (in the same package)
import java.util.Arrays;
import java.util.Random;

public class SortingAlgorithms {
  public static void main(String[] args)
  {
    final int N = 10;
    Integer[] ar = new Integer[N];

    // load random Integer's
    Random ran = new Random();
    for (int i = 0; i < N; ++i)
      ar[i] = ran.nextInt(20); 

    // print ar
    System.out.println("Before: " + Arrays.toString(ar));

    // sort ar 
    Bubble.sort(ar); // (**) sort() in Bubble is a static method

    // print ar again
    System.out.println("After:  " + Arrays.toString(ar));
  }
}

2. Sorting Algorithm Properties

In addition to sorting the values, there are other properties that differentiate sorting algorithms that may be important in applications.
Before (sorted in decreasing order by date)   After sorting by amount (in decreasing order) 
					      					      
 7-Mar-2006 10957.31 10980.00		       2-Mar-2006 11052.57 11025.00
 6-Mar-2006 11022.47 10958.00		      27-Mar-2000 11093.25 11025.00
 2-Mar-2006 11052.57 11025.00		       7-Mar-2006 10957.31 10980.00
22-Feb-2001 10527.80 10526.00                 30-Mar-2000 11008.17 10980.00
21-Feb-2001 10721.29 10526.00                  6-Mar-2006 11022.47 10958.00
30-Mar-2000 11008.17 10980.00		      22-Feb-2001 10527.80 10526.00
27-Mar-2000 11093.25 11025.00		      21-Feb-2001 10721.29 10526.00    

3. Various Sorting Algorithms

 Below are some sorting algorithms used in computer science.  You can also find many animations of various sorting algorithms available on the internet, for instance Sort Animation.

Algorithm Code
1. Selection
  • O(n2) time
  • No extra space
  • Not stable
  • Algorithm is simple, but time complexity (O(n2)) is not as good as other algorithms.

    void Selectsort (int[] data) 
    {
       int n = data.length;
       int min,tmp,i,j,min_id;
    
       for (i=0; i<n-1; i++) {
           min = data[i];
           min_id = i;
           for (j=i+1; j<n; j++)
               if (data[j] < min) {
                  min = data[j];
                  min_id = j;
               }
           tmp = data[i];
           data[i] = data[min_id];
           data[min_id] = tmp;
       }
    }
    2. Insertion [example]
  • O(n2) time
  • No extra space
  • Stable
  • Time complexity (O(n2)) is not as good as other algorithms, but runs fast when the array is short or nearly sorted already.

    Similar to how we sort/arrange cards.

    void Insertionsort (int[] data) 
    {
       int n = data.length;
       int tmp,i,j;
    
       for (j=1; j<n; j++) {
           i =j - 1;
           tmp = data[j];
           while ( (i>=0) && (tmp < data[i]) ) {
               data[i+1] = data[i];
               i--;
           }
           data[i+1] = tmp;
       }
    }
    3. Bubble
  • O(n2) time
  • No extra space
  • Stable
  • Similar characteristics as Insertion sort.

    Always swap two adjacent elements, and move down the array -- like a bubble travel through the array.

    void Bubblesort (int[] data) 
    {
       int n = data.length;
       int tmp,i,j;
    
       for (i=0; i<n-1; i++) {
           for (j=0; j<n-i-1; j++)
                if (data[j] > data[j+1]) {
                   tmp = data[j];
                   data[j] = data[j+1];
                   data[j+1] = tmp;
               }
       }
    }
    4. Quicksort [example]
  • O(n2) time -- worst case
  • O(n·lg(n)) time
  • -- average case
  • No extra space
  • Not stable
  • One of the most widely used sorting algorithms.  Fast, but not stable.

    Uses a strategy called "Divide-and-Conquer".

    Pick a partition element called pivot, and split the array in two parts -- one with elements larger than the pivot and other other with elements smaller than the pivot.
    There are several methods to selecting the methods, for example, the first element and the median of three.

    void quicksort (int[] a, int lo, int hi)
    {
    //  lo is the lower index, hi is the upper index
    //  of the region of array a that is to be sorted
        int i=lo, j=hi, temp;
        int x=a[(lo+hi)/2];
    
        //  partition
        do
        {    
            while (a[i]<x) i++; 
            while (a[j]>x) j--;
            if (i<=j)
            {
                // swap a[i] and a[j]
                temp=a[i]; a[i]=a[j]; a[j]=temp;
    
                // increment i and decrement j
                i++; j--;
            }
        } while (i<=j);
    
        //  recursive calls
        if (lo<j) quicksort(a, lo, j);
        if (i<hi) quicksort(a, i, hi);
    }
    
    5. Merge [example]
  • O(n·lg(n)) time
  •  
  • O(n) extra space  (*)
  • Stable
  • Uses a strategy called "Divide-and-Conquer".

    Requires an extra temporary storage of the same size of the array (*).

    Problem: Sort elements in a list L of length n 
            (whose index is 0 through n-1) in an ascending order.
    Input: L (a list), and i, j (indices)
    Output: nothing.  Elements in L will be sorted in place.
    
    procedure MergeSort(L, i, j)
    1.  if i = j then       // base case; 1-element sequence
    2.    return
    3.  m := floor((i+j)/2)
    4.  MergeSort(L, i, m)  // recursive call to left half
    5.  MergeSort(L, m+1, j)// recursive call to right half
    6.  Merge(L, i, m, j)   // merge 2 sequences L[i...m] & L[m+1...j]
    end MergeSort
    6. Heap
  • O(n·lg(n)) time
  • No extra space
  • Not stable
  • Utilizes a heap.  Simple and fast, but a heap must be constructed, which takes additional O(n) time.

     

    4. Alternate Orderings -- The Comparator<T> Interface

    There are many ways to implement Comparator's for a class.  Two approaches are introduced here.

    1. External public class which implements Comparator -- access necessary information to determine the order through public methods.
      public class PersonAgeComp implements Comparator<Person>
      {
        public int compare(Person p1, Person p2)
        {
          int diff = p1.getAge() - p2.getAge(); // a public method getAge() in Person
          return diff;
        }
      }
      //==================================
      // a client program
      public class Prog1
      {
        public static void main(String[] args)
        {
          Person[] psar = { new Person("Alice Cooper", 58), new Person("Britney Spears", 21), ...};
          // A comparator object
          PersonAgeComp pac = new PersonAgeComp();
      
          // Call Arrays.sort() with pac -- to sort Person's by age
          Arrays.sort(psar, pac);
      
      
    2. Inner class (so that Comparator can access private members)
      public class Person 
      {
        // instance variables
        private String name;
        private int age;
      
        //-------------
        public static class PersonAgeComp implements Comparator<Person>
        {
          public int compare(Person p1, Person p2)
          {
            int diff = p1.age - p2.age; // age is a private member
            return diff;
          }
        }
        //-------------
        ...
      }
      //==================================
      // a client program
      public class Prog1
      {
        public static void main(String[] args)
        {
          Person[] psar = { new Person("Alice Cooper", 58), new Person("Britney Spears", 21), ...};
      
          // Call Arrays.sort() with two arguments
          Arrays.sort(psar, new Person.PersonAgeComp()); // 2nd parameter is a PersonAgeComp object