像任何其他排序一样,选择排序可以按照升序或降序的方式修改排序。按升序排序的方法如下:数组中最小的值被定位并移动到 Element 0,然后定位下一个最小值并移动到 Element 1,这个过程一直持续到所有元素都按照正确的顺序排列。
现在来看一看在排列下面数组的元素时,选择排序是如何工作的:
选择排序从 Element 0 开始扫描数组,并找到最小值的元素。这个元素的内容然后与 Element 0 的内容交换。在该示例中,Element 5 中存储的 1 是最小的值,所以它与存储在 Element 0 中的 5 交换。这完成了第一趟,现在的数组显示如下:
该算法然后重复该过程,但是因为 Element 0 已经包含数组中的最小值,所以可以将其排除在过程之外。接下来进行第二趟,算法在 Element 1 处开始扫描。它在数组的未排序部分中查找最小值,结果找到了 Element 2 中的 2。因此,Element 2 与 Element 1 交换。数组现在显示如下:
再次重复这个过程,但是这次扫描从 Element 2 开始。算法将发现 Element 5 包含下一个最小值,于是将该元素的内容与 Element 2 的内容交换,导致数组显示如下:
接下来,扫描从 Element 3 开始。其内容与 Element 5 的内容交换,导致数组显示如下:
到现在这个阶段,只剩下两个元素需要排序。选择排序算法发现 Element 5 的值小于 Element 4 的值,所以两者交换。于是数组完成了最终的排列:
以下是选择排序算法的伪代码:
For startScan = 0 to the next-to-last array subscript Set index to startScan Set minIndex to startScan Set minValue to array[startScan] For index = (startScan + 1) to the last subscript in the array If array[index] is less than minValue Set minValue to array[index] Set minIndex to index End If Increment index End For Set array[minIndex] to array[startScan] Set array[startScan] to minValue End For
与冒泡排序一样,选择排序使用一对嵌套循环,在这个例子中是两个 for 循环。
外循环在每一趟排序时迭代一次。其循环控制变量是 startScan,它保存了数组元素的下标,该下标所代表的元素将在排序时接收其正确的值:
- 第一趟排序时,startScan 取值为 0,在找到最小值之后,最小值所在位置和 Element 0 位置进行值的交换,Element 0 获得了最小值。
- 在第二趟排序时,startScan 取值为 1,在剩下的值中寻找最小值,找到之后即和 Element 1 位置进行值的交换。
这个过程不断进行,直到从 Element 0 位置到倒数第 2 个位置的元素都已经获得了正确的值。一旦该过程完成,则数组最后一个元素的值自然也是最大值,于是就不需要外部循环再次迭代了。由此可见,如果数组中有 N 个数据,则意味着需要迭代 N-1 趟。
每一趟排序过程中,内部循环的任务是查找最小值,以便与 startScan 位置中的值进行交换。在迭代开始之前,minIndex 被设置为 startScan,并且 minValue 被设置为 startScan 位置中的当前值。内部循环然后从 startScan+1 的下标位置开始查找数组中剩余的值。如果它发现一个值要小于当前存储在 minValue 中的值,则使用这个新的更小的值取代 minValue 中原有的值,并且使用新最小值所在的下标取代 minIndex 中存储的下标。
一旦内部循环完成其迭代,则 minIndex 将保存最小元素的下标索引,然后外部循环就会将该元素的内容和 array[startScan] 的内容交换,并且使 startScan 递增 1。请注意,如果未发现比 startScan 位置的值更小的元素,则 minIndex 仍将等于 startScan,那么 startScan 位置中的值就会和它自己交换,实际上就是保持不变。
以下函数使用了选择排序方法,以升序方式排列整数数组中的值。它接收两个参数。第一个形参 array 接收要排序的数组,第二个形参 size 则指示数组中存储了多少个值。
void selectionSort (int array[], int size) { int startScan, minIndex, minValue; for (startScan = 0; startScan < (size - 1); startScan++) { minIndex = startScan; minValue = array[startScan]; for (int index = startScan + 1; index < size; index++) { if (array[index] < minValue) { minValue = array[index]; minIndex = index; } } array[minIndex] = array[startScan]; array[startScan] = minValue; } }
如前所述,选择排序需要交换的次数要少于冒泡排序。事实上,正如上例所示,它每一趟只需要交换一个数据。外部循环的每一次迭代都可以将一个值放置到正确的位置,不仅如此,己经正确的值和数组位置在后面的排序中还无须再次检测。
但是,值得注意的是,选择排序不使用标记变量(冒泡排序中的 madeAswap 就是一个标记变量)。这是因为,即使某个数组位置已经保存了下一个最小的值,从而导致它的值在下一趟排序过程中不会改变,但这并不意味着数组已经完成排序,因为其他值可能尚未移动到它们的正确位置。
下面的程序演示了选择排序函数的用法:
//This program uses the selection sort algorithm to sort an array in ascending order. #include <iostream> using namespace std; //Function prototypes void selectionSort (int [], int); void showArray(const int [], int); int main() { const int SIZE = 6; // Array of unsorted values int values[SIZE] = {5, 7, 2, 8, 9, 1}; // Display the values cout << "The unsorted values are/n"; showArray(values, SIZE); //Sort the array selectionSort(values, SIZE); // Display the values again cout << "The sorted values are/n"; showArray(values, SIZE); return 0; } void selectionSort(int array[], int size) { int startScan, minIndex, minValue; for (startScan = 0; startScan < (size - 1); startScan++) { minIndex = startScan; minValue = array[startScan]; for(int index = startScan + 1; index < size; index++) { if (array[index] < minValue) { minValue = array[index]; minIndex = index; } } array[minIndex] = array[startScan]; array[startScan] = minValue; } } void showArray(const int array[], int size) { for (int count = 0; count < size; count++) cout << array [count] << " "; cout << endl; }
程序输出结果:
The unsorted values are
5 7 2 8 9 1
The sorted values are
1 2 5 7 8 9
原创文章,作者:奋斗,如若转载,请注明出处:https://blog.ytso.com/22114.html