7.13.1. Selection Sort

Selection sort is small, relatively easy to understand, and works well for small arrays (a few tens of elements). These characteristics make it an excellent example of using arrays. However, selection sort is sensitive to the size of the data (i.e., the size of the array). In CS 2420, you will learn about run order and Big-O notation. Computer scientists use these tools to express how long an algorithm typically takes to solve a problem in terms of the size or amount of data it processes. Selection sort has a run order of O(n2), which means that doubling the data size quadruples the time needed to sort it. Faster sorting algorithms are desirable for processing larger amounts of data, and you will study more efficient algorithms, such as quicksort and merge sort, in CS 2420.

The selection sort algorithm is named for its basic behavior. It selects the smallest value in an array, swaps it with the element at the top of the array, effectively shrinks the array by one element, and then repeats the process until the array size is 0 and the array sorted. (We can modify the algorithm to select the largest element and swap it with the element at the bottom of the array.) Selection sort doesn't change the data array size; instead, it changes the value stored in a variable, top, that indexes into the array. For the rest of this discussion, we'll use the term sub-array to help clarify this organization.

Implementing selection sort requires two loops, one nested inside the other. The outer loop repeats the two main tasks of selecting the smallest value and swapping it with the top element. The outer loop also "shrinks" the sub-array by advancing the "top" index variable. These steps are conveniently carried out with a for-loop: for (int top = 0; top < size; top++) The inner loop carries out the selection task by it identifying the smallest element in the sub-array, which it does by comparing the element at the top of the sub-array with the remaining sub-array elements. When dealing with simple or primitive data, the "less-than" operator is sufficient for comparing and ordering the array elements. More complex data requires creating an appropriate ordering function, which is discussed in the next chapter. Figure 1 illustrates the swapping task.

A picture illustrating a sub-array, or part of an array. The inner for-loop has identified the smallest element in the sub-array. With the top and smallest (min) elements identified, the swap operation is about to begin. The smallest (min) element is copied to temp. The top element is copied to the min location. temp is copied to the top location.
(a)(b)(c)(d)
Swapping the smallest and top elements. The green box represents the element stored at the top of the current sub-array and the blue box represents the smallest element remaining in the sub-array.
  1. The initial state of the array. The variables top and min are indexes into the data array. The sub-array is that part of the data array that lies between the top index and the bottom of the data array. The min index is the smallest element in the sub-array as identified by the selection task.
  2. Swapping the smallest and the top elements takes three steps. The first step copies or saves the smallest value in the sub-array into a temporary variable.
  3. In a sense, saving the smallest array element "frees" that location in the array. The second step copies or saves the value at the top of the array into this now "free" or "empty" location.
  4. The final step copies the value stored in the temporary variable to the top of the sub-array.

Simple Data

The main function is a simple driver that tests the selection sort function. The following examples present three slightly different versions of the selection sort algorithm. The first version is a single function; the second and third versions define a swap function that swaps array elements. Other than the function prototypes appearing at the top, the main functions are the same for all three versions.

#include <iostream>
using namespace std;


void ssort(char* data, int size);			// all versions
//void swap(char* min, char* top);			// version 2 only
//void swap(char& min, char& top);			// version 3 only


int main()
{
	char	data[] = { 'S','E','E','T','H','E','Q','U','I',		// (a)
			'C','K','R','E','D','F','O','X' };
	int	size = sizeof(data) / sizeof(char);			// (b)

	ssort(data, size);						// (c)

	for (int i = 0; i < size; i++)					// (d)
		cout << data[i] << endl;

	return 0;
}
A selection sort testing driver.
  1. Test data
  2. The array size; NOTE: sizeof does NOT work with function arguments - that is, we can't calculate the size of the data array in the ssort function (see Figure 5)
  3. Call the selection sort function
  4. Print the sorted array

ssort Version 1

void ssort(char* data, int size)
{
	for (int top = 0; top < size; top++)		// (a)
	{
		// select
		int min = top;				// (b)
		for(int i = top + 1; i < size; i++)	// (c)
			if (data[i] < data[min])	// (d)
				min = i;		// (e)

		// swap
		char temp = data[min];			// (f)
		data[min] = data[top];			// (g)
		data[top] = temp;			// (h)
	}
}
ssort function (1).
  1. For each element at the top of the sub-array, select the smallest element and swap it with the top element.
  2. Initialize the min index (assume for a moment that the top element is the smallest).
  3. Beginning with the second element in the sub-array and for each of the remaining elements in the sub-array
  4. compare the smallest element with the other elements in the sub-array one at a time.
  5. If a smaller element is found, update location of the current smallest element.
  6. Save the smallest element in a temporary variable.
  7. Move the current top element to the location that previously stored the smallest element.
  8. Move the smallest element to the top of the sub-array.

ssort: Version 2

void ssort(char* data, int size)
{
	for (int top = 0; top < size; top++)		// (a)
	{
		// select
		int min = top;				// (b)
		for(int i = top + 1; i < size; i++)	// (c)
			if (data[i] < data[min])	// (d)
				min = i;		// (e)

		swap(&data[min], &data[top]);		// (f)
	}
}


void swap(char* min, char* top)				// (g)
{
	char temp = *min;				// (h)
	*min = *top;					// (i)
	*top = temp;					// (j)
}
ssort function (2) swap. The second version of the selection sort example is similar to the first (steps a-e are identical), but the second version replaces the three swapping statements with a swap function. The function must change the values stored in two variables (i.e., in two array elements). Pass by value cannot make the change, so the swap function must use pass by pointer (this version) or pass by reference (version 3).
  1. For each element at the top of the sub-array, select the smallest element and swap it with the top element.
  2. Initialize the min index (assume for a moment that the top element is the smallest).
  3. Beginning with the second element in the sub-array and for each of the remaining elements in the sub-array
  4. compare the smallest element with the other elements in the sub-array one at a time.
  5. If a smaller element is found, update location of the current smallest element.
  6. Calling the swap function, which has two pointer arguments. Indexing into an array produces a single element, so the address-of operator is used to get the address of the element.
  7. The swap function header: the two arguments that are swapped are passed by pointer. Both variables must be dereferenced when the values that they point to are used.
  8. Save the smallest element in a temporary variable. The * is the dereference or indirection operator.
  9. Move the current top element to the location that previously stored the smallest element. The * is the dereference or indirection operator.
  10. Move the smallest element to the top of the sub-array. The * is the dereference or indirection operator.

ssort: Version 3

void ssort(char* data, int size)
{
	for (int top = 0; top < size; top++)		// (a)
	{
		// select
		int min = top;				// (b)
		for(int i = top + 1; i < size; i++)	// (c)
			if (data[i] < data[min])	// (d)
				min = i;		// (e)

		swap(data[min], data[top]);		// (f)
	}
}


void swap(char& min, char& top)				// (g)
{
	char temp = min;				// (h)
	min = top;					// (i)
	top = temp;					// (j)
}
ssort function (3) with swap. The third version of the selection sort example is similar to the first and second (steps a-e are again the same), but like the second version, the third version replaces the three swapping statements with a swap function, but in this version the arguments are passed by reference.
  1. For each element at the top of the sub-array, select the smallest element and swap it with the top element.
  2. Initialize the min index (assume for a moment that the top element is the smallest).
  3. Beginning with the second element in the sub-array and for each of the remaining elements in the sub-array
  4. compare the smallest element with the other elements in the sub-array one at a time.
  5. If a smaller element is found, update location of the current smallest element.
  6. Calling the swap function and passing two array elements by reference.
  7. The swap function header: the two arguments that are swapped are passed by reference.
  8. Save the smallest element in a temporary variable.
  9. Move the current top element to the location that previously stored the smallest element.
  10. Move the smallest element to the top of the sub-array.

Object Data

Review
#include <iostream>
#include <iomanip>
using namespace std;

struct student
{	char	*name;
	int	id;
	double	gpa;
};

void ssort(student* data, int size);

int main()
{
	student students[] = {
			{ "Dilbert", 123, 3.5 },
			{ "Wally", 456, 2.0 },
			{ "Alice", 987, 3.9 },
			{ "Asok", 730, 3.8 },
			{ "Catbert", 501, 3.0 },
			{ "Pointy Haired Boss", 666, 1.0 },
			{ "Dogbert", 111, 4.0 }
		};
	int	size = sizeof(students) / sizeof(student);

	ssort(students, size);

	cout.precision(1);				// configure cout to format the gpa on output
	cout.setf(ios::left | ios::fixed);

	for (int i = 0; i < size; i++)
		cout << left << setw(5) << students[i].id <<
			setw(20) << students[i].name <<
			right << setw(5) << students[i].gpa << endl;

	return 0;
}
Tesing ssort with an array of structures. Create a complete program by combining this driver with one of the following versions of ssort.

Version 4

void ssort(student* data, int size)
{
	for (int top = 0; top < size; top++)
	{
		// find the smallest element in the sub-array top..size-1
		int min = top;
		for(int i = top + 1; i < size; i++)
			if (data[i].id < data[min].id)
				min = i;	// update location of the smallest element

		// swap the current top element with the smallest element
		student temp = data[min];	// save the smallest element
		data[min] = data[top];		// move the current top to smallest
		data[top] = temp;		// move the smallest to the top
	}
}
sort orders the structures by student ID. This version swaps the min and top elements with three statements at the bottom of the outer for-loop.

Version 5

void ssort(student* data, int size)
{
	for (int top = 0; top < size; top++)
	{
		// find the smallest element in the sub-array top..size-1
		int min = top;
		for(int i = top + 1; i < size; i++)
			if (data[i].id < data[min].id)
				min = i;	// update location of the smallest element

		// swap the current top element with the smallest element
		swap(data[top], data[min]);
	}
}

void swap(student* param1, student* param2)
{
	student temp = *param2;
	*param2 = *param1;
	*param1 = temp;
}
ssort uses a swap function, orders by ID.

Version 6

void ssort(student* data, int size)
{
	for (int top = 0; top < size; top++)
	{
		// find the smallest element in the sub-array top..size-1
		int min = top;
		for(int i = top + 1; i < size; i++)
			if (data[i].id < data[min].id)
				min = i;	// update location of the smallest element

		// swap the current top element with the smallest element
		swap(data, top, min);
	}
}

void swap(student* data, int index1, int index2)
{
	student temp = data[index1];
	data[index1] = data[index2];
	data[index2] = temp;
}
Passing an array to the swap function. We passed the two array elements we wanted to swap to the previous versions of the swap function. We pass the entire array and two indexes to the swap function in this example. Although we pass the entire array, the function doesn't need the array's size, but it must assume that the two index values are within bounds.

Downloadable Code

Complete programs. Tabs tops set at eight spaces.

ViewDownload
Simple Data
ssort1.cpp ssort1.cpp
ssort2.cpp ssort2.cpp
ssort3.cpp ssort3.cpp
Structure Object
ssort4.cpp ssort4.cpp
ssort5.cpp ssort5.cpp
ssort6.cpp ssort6.cpp