Insertion Sort
Many applications require that data be ordered and maintained. Insertion sort is one sorting algorithm that puts data in order. Some examples of humans manually using insertion sort include sorting a deck of cards, or arranging books on a bookshelf.
The Insertion Sort
One common sorting approach is based on code that assumes that the first part of an array is ordered and then adds successive items to this array segment until the entire array is sorted. To understand this approach, we first consider how to add one item to an ordered array segment. We then apply this work to each array element in turn to yield an ordered array.
Maintaining An Ordered Array Segment
Suppose items data[0], ..., data[last-1]
are ordered in array data:
| 3 | 7 | 9 | 10 | 18 | 27 | 33 | 37 |
The following code inserts an item into the array, so
that items data[0], ..., data[last] become ordered:
int position = last-1; // index to place the new item
while ((position>= 0) && data[position] > item)
{
data[position+1] = data[position];
position--;
}
data[position+1] = item;
Using this basic insertion step, an array data can be
sorted iteratively according to the following outline:
-
Consider
data[0]as a sorted initial segment of arraydata. (That is, in the example, considerlast= 0.) -
Insert
data[1]into segmentdata[0]to get ordered segmentdata[0], data[1]. -
Insert
data[2]into segmentdata[0], data[1]to get ordered segmentdata[0], data[1], data[2]. -
Insert
data[3]into segmentdata[0], ..., data[2]to get ordered segmentdata[0], ..., data[3]. -
Insert
data[4]into segmentdata[0], ..., data[3]to get ordered segmentdata[0], ..., data[4]. - Et cetera.
This outline gives rise the the following code, called an insertion sort.
// method to sort using the insertion sort
// parameters: data, the array to be sorted
// length, the size of the data array
void insertionSort (int data[], int length)
{
for (int boundary = 1; boundary < length; boundary++)
{
int item = data[boundary];
int position = boundary-1;
while ((position >= 0) && data[position] > item)
{
data[position+1] = data[position];
position--;
} // while
data[position+1] = item;
} // for
} // insertionSort
It is important to notice that the item being compared is not
switching place with each item it compares to. The items that are
compared against are shifted; the element being compared is inserted.
The following visualization demonstrates how insertion operates,
showing the item indexed by boundary in red.
Insertion Sort Characteristics
This sorting algorithm is relatively simple, efficient for small data sets and data sets that are already partially sorted, stable in the sense that it does not switch identical elements, and only requires a constant amount of additional memory space (that is, the amount of memory for the set of elements, plus memory for one element of the set). The amount of time this algorithm takes to sort a set is dependent upon the set itself. For a set with n elements, if the set is sorted (or nearly so), the algorithm takes only a single time unit for each element, so it takes N time units. On the other hand, if the set is in reverse order (that is, largest to smallest), the time approaches N2. You will see the previous two statements proven in a later course.
Insertion Sort with Column-Major Order
In a previous module, you learned about arrays. In this module, you learned about multi-dimensional arrays. Below is an example of initializing a two-dimensional array:
int array[2][5] = { {4, 3, 8, 2, 5}, {2, 1} };
In this example, the array of integers array has two rows,
with the first row initialized with the values 4, 3, 8, 2, and 5, and
the second row with the first two values initialized (2 and 1), and the
remaining values are implicitly initialized to 0. So, a human-readable
version of this two-dimensional array looks like the following:
| 4 | 3 | 8 | 2 | 5 |
| 2 | 1 | 0 | 0 | 0 |
However, when you initialize the array in C, the program reserves a contiguous span of memory for the array and assigns the values that have been specified. So, the above array is represented in memory as the following:
| 4 | 3 | 8 | 2 | 5 | 2 | 1 | 0 | 0 | 0 |
As you notice, the C program puts the array in memory a row at a time, beginning from the first row. This is called row-major order, and is the C standard. Some other programming languages, such as FORTRAN and Matlab, use column-major order, in which each column is stored in memory contiguously. So, in column-major order, the array looks like the following:
| 4 | 2 | 3 | 1 | 8 | 0 | 2 | 0 | 5 | 0 |
When sorting a single-dimensional array in C, the most common method is to sort the elements from smallest to largest. Though sorting a multi-dimensional array is much less frequent, one method is to perform essentially the same method by sorting each row, so the rows are in order, but the columns are not.
Self-Checks
You should be able to answer each of the following questions:- The reading claims that insertion sort is better for nearly-sorted lists than reverse-ordered lists. Why?
- How much extra memory is required for each sort?
- If the list is composed of four identical elements, how many elements change position when insertion sort is used? Why?
- Why might some people use insertion sort in real life?
-
For each of the following lists, draw the result of each insertion
of the insertion sorting routine. You do not need to show the
result of each comparison, just the final insertion of the element.
- 5, 4, 1
- 3, 1, 3
- 2, 5, 4, 0
- 6, 8, 3, 5, 1, 9, 2, 2
