选择排序与冒泡排序类似,采用逐轮扫描最值然后将其置于顶端的方式完成数组排序。区别是,冒泡法采取的是依次比较相邻元素并不断交换逆序元素的策略,逐步将最值向前推进;而选择排序法采取标记最值位置的策略,扫描过程中不交换元素位置,只修改标记,直至找到最值,将最值交换到顶端。相对于冒泡法,可显著减少交换次数,每轮扫描至多交换1次。
原理:设置最值位置标记,逐轮扫描未排序部分元素最值。每一轮扫描过程中,以未排序部分首部元素为基准(将位置标记设置为未排序首元素下标)与后续元素进行比较。遇到更小(或更大)的元素则将位置标记修改为其下标,直至扫描完成,将标记位置的元素与未排序部分首元素交换位置。至多进行n-1轮扫描,序列完全有序。
步骤:
第 1 轮,所有元素均未经排序,将标记设置为第一个元素下标,以第一个元素为基准依次与后面的元素进行比较,不断修改最值标记为较小元素的下标,经过 n-1 次比较位置标记必将为最值下标,然后将最值与第一个元素交换位置。此时首元素称作已排序部分,其余元素为未排序部分。
第 i 轮,前 i-1 个元素为已排序部分,将标记设置为第 i 个元素下标,并以第 i 个元素为基准依次与后面的元素进行比较,不断修改最值标记为较小元素的下标,经过 n-i 次比较位置标记必将为最值下标,然后将最值与未排序部分第一个元素(即第 i 个元素)交换位置。此时前 i 个元素有序,其余元素无序。
第 n-1 轮,将标记设置为第 n-i 个元素下标,然后与最后一个元素进行比较,较小者前置,至此所有元素完成排序。
代码:
void selectionsort(int A[], int n)
{
int mark;
for (int i = 1; i < n; i++) //i的取值范围为[1,n-1],共n-1轮
{
mark = i-1; //初始化标记,元素下标从零开始,比轮次落后1
for (int j = i; j < n; j++) //j的取值范围为[i,n-1],共比较n-1-i+1次,即n-i次
{
if (A[mark]>A[j]) //最值不在标记处则修改标记
mark = j;
}
if (mark != i - 1) //标记若修改则将最值置换至顶端
{
A[mark] = A[mark] + A[i - 1];
A[i-1] = A[mark] - A[i - 1];
A[mark] = A[mark] - A[i - 1];
}
}
}