7.14.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, the selection sort is sensitive to the data size (i.e., the array's size). In CS 2420, you will learn about run order and Big-O notation. Computer scientists use these tools to express the relative time an algorithm takes to solve a problem, expressing the runtime in terms of the data's size. 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, effectively shrinks the array by one element, and then repeats the process until the array size is 0 and the array is 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 selects the smallest value and swaps it with the top element. The outer loop also "shrinks" the sub-array by advancing the top index variable. A for-loop, for (int top = 0; top < size; top++), conveniently carries out these steps. The inner loop performs the selection task by identifying the smallest element in the sub-array, which it does by comparing the element at the top 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 runs. The algorithm copies the smallest (min) element to temp. The algorithm copies the top element 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 remaining element.
  1. The initial state of the array. The variables top and min are indexes in 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 the function finds a smaller element, it updates the location of the current smallest element.
  6. Save the smallest element in a temporary variable, "freeing" that location in the array.
  7. Move the current top element to the "freed" location, previously storing 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 the function finds a smaller element, it updates the 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 function passes the parameters by pointer, so it must dereference them when using the values they point to.
  8. Save the smallest element in a temporary variable. The * is the dereference or indirection operator.
  9. The assignment moves the current top element to the location previously storing 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 through e are again the same). However, like the second version, the third version replaces the three swapping statements with a swap function, but the function in this version passes the parameters 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 the function finds a smaller element, it updates the location of the current smallest element.
  6. Calling the swap function and passing two array elements by reference.
  7. The swap function header: the function passes the parameters by reference.
  8. Save the smallest element in a temporary variable.
  9. Moves the current top element to the location previously storing 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;
}
Implementing ssort with a swap function.

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. In the previous figure, the program passed the two array elements to swap to the swap function as pointers. The program passes the entire array and two indexes to the swap function in this version. Although the program passes 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. Tab stops are 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