43A. Sorting a Linked List Using Insertion Sort


Insertion into a sorted list

We have seen how to insert a value into a sorted linked list in such a way that the list remains sorted, and we used it to derive a nondestructive algorithm to sort a linked list nondestructively. Here is the code that we derived for doing the insertion.

  // insert(x,L) inserts x into list L, changing L.
  //
  // L must be in ascending order when insert is called,
  // and x is inserted in the correct place so that
  // L is sorted after the insertion.

  void insert(const int x, List& L)
  {
    if(L == NULL || x <= L->head)
    {
      L = cons(x, L);
    }
    else
    {
      insert(x, L->tail);
    }
  }

Suppose that we want to sort a linked list destructively, rearranging the list cells. The insert function above will not work because it uses cons, which builds a new list cell, precisely what we want to avoid. But for our purposes here, we want a function that is given a cell containing x and inserts that cell into L. Here is the modified insertion function.

  // insertCell(C,L) inserts cell C into list L, changing L.
  //
  // L must be in nondescending order when insertCell
  // is called. Cell C is inserted, preserving its head
  // value, in the correct place so that L is in
  // nondescrending order after the insertion.

  void insertCell(ListCell* C, List& L)
  {
    if(L == NULL || C->head <= L->head)
    {
      C->tail = L;
      L = C;
    }
    else
    {
      insertCell(C, L->tail);
    }
  }

Sorting a linked list using Insertion Sort

Let's use insertCell to write a function that sorts a linked list by rearranging the list cells. Here are thoughts about that.

  1. An empty list is in nondescending order in a trivial way. Do nothing to it.

  2. To sort a nonempty list L, sort the tail of L, then insert the cell at the head of L into the sorted tail.

That leads to the following sorting function, called Insertion Sort.

  // InsertionSort(L) sorts list L into ascending order,
  // changing list L.

  void InsertionSort(List& L)
  {
    if(L != NULL)
    {
      InsertionSort(L->tail);
      insertCell(L, L->tail);
    }
  }

They don't come much simpler than that.

Notice that pointer L can be viewed as a pointer to a linked list or, as in the call to insertCell, as a pointer to the first cell in the linked list. Both viewpoints are valid.