Insertion SortTopSortingSelection Sort

Selection Sort

First, we will look at this procedure:

What I have described is a form of a selection sort - at each step, we select the item that goes into the next position of the array, and put it there. This gets us one step closer to a solution.

This (hopefully) sounds like a job for a recursive algorithm. If we want to describe it that way, we'll need to make sure we have a base case (stopping condition) and a way to reduce the problem to a smaller version of the problem that can be solved by a recursive call.

Let's put playing cards aside and return to an array of int. Our base case is an array of either 0 or 1 elements. In either case, we know that the job is done, since any array of 0 or 1 elements is already sorted. The recursive step involves first finding the smallest element and putting it at the end of the sorted portion of the array (swap it with whatever happened to be in that position), then doing a selection sort on the remaining unsorted portion of the array.

Here is a method that does this:

  public void sort(int[] array) {
    selectionSort(array, 0);
  }
  
  /*
   * PRE: startIndex must be valid index for array
   * POST: Sorts array from startIndex to array.length.
   */
  void selectionSort(int[] array, int startIndex) {
    if (startIndex < array.length - 1) {
      // find smallest element in rest of array
      int smallest = indexOfSmallest(array, startIndex);

      // move smallest to index startIndex
      swap(array, smallest, startIndex);

      // sort everything in the array after startIndex
      selectionSort(array, startIndex + 1);
    }
  }

  /*
   * Return index of smallest number in array between
   * startIndex and array.length.
   * PRE: startIndex must be valid index for array
   * POST: returns index of smallest value in range startIndex - array.length
   */
  int indexOfSmallest(int[] array, int startIndex) {
    int smallIndex = startIndex;
    for (int i = startIndex + 1; i < array.length; i++) {
      if (array[i] < array[smallIndex]) {
        smallIndex = i;
      }
    }
    return smallIndex;
  }

  /*
   * PRE: i and j must be valid indices for array
   * POST: exchanges the values stored in array[i] and array[j]
   */
  void swap(int[] array, int i, int j) {
    int temp = array[i];
    array[i] = array[j];
    array[j] = temp;
  }

Note that if startIndex < array.length - 1, then the array has at least two elements left. If it has 0 or 1, then selectionSort does nothing.

The method indexOfSmallest(array, startIndex) finds the index of the smallest element in array[statIndex],..., array[array.length-1].

The method call swap(array, startIndex, smallestIndex) swaps the smallest element of the array with the one at startIndex. As a result the smallest element in array[statIndex],..., array[array.length-1] will end up in elementArray[startIndex].

It is also possible to write this iteratively:

  public void iterativeSelectionSort(int[] array) {
    for (int i = 0; i < array.length - 1; i++) {
      int smallest = indexOfSmallest(array, i);
      swap(array, smallest, i);
    }
  }

How long does this algorithm take? As we did with searching, we won't try to calculate an exact time, but we will estimate the cost by computing the number of comparisons done in sorting an array.

Suppose the original array has n elements, where n > 1. Then it takes n-1 comparisons to find the smallest element of the array (compare the first with the second, the smaller of those with the third, etc.). In general, the number of comparisons needed to find the smallest element is one less than the number of elements to be sorted. Once this element has been put into the last slot of the array, we need to sort the remaining n-1 elements of the array. By the argument above, it takes n-2 comparisons to find the largest of these. We continue with successive stages taking n-3, n-4, all the way down to the last pass through when there are only two elements and it takes only 1 comparison. (Once we get down to 1 element there is nothing to be done.)

Thus it takes S = (n-1) + (n-2) + (n-3) + ... + 3 + 2 + 1 comparisons to sort a list of n elements. We can compute this sum by writing the list forwards and backwards, and then adding the columns:

   S = (n-1) + (n-2) + (n-3) + ... +   3   +   2   +   1
   S =   1   +   2   +   3   + ... + (n-3) + (n-2) + (n-1)
   -------------------------------------------------------
  2S =   n   +   n   +   n   + ... +   n   +   n   +   n   = (n-1)*n 

Therefore S = (n2 - n)/(2). The graph of this as n increases looks like n2 - a parabola. Therefore, selection sort takes n2 time, which is much worse than the behavior for the searching algorithms we saw last time.


Insertion SortTopSortingSelection Sort