选择排序是一种简单直观的交换类排序算法。它的核心思想是每一轮从未排序区间当中找到最小(升序)的元素,将它和未排序区间的第一个元素进行交换。
不同于冒泡排序不断相邻交换,选择排序每一轮只做一次交换。算法逻辑简单,适合算法入门学习。
选择排序把数组划分为左右两部分,左边是已经排好序的部分,右边是待处理未排序部分。
每一趟遍历未排序区域,记录最小值所在下标;一趟查找结束后,把最小值交换到未排序区域最左侧。循环往复,直到全部元素有序。
n个元素数组,最多执行 n‑1 轮选择;每一轮完成后已排序区间长度+1。
以数组 [5, 3, 8, 4, 2] 为例,演示升序选择排序全过程。
第1轮:未排序区间全部数组[5,3,8,4,2],找到最小值2,和下标0元素5交换,数组变为[2,3,8,4,5]。下标0变为有序。
第2轮:未排序区间[3,8,4,5],最小值3本身就在头部,无需交换。下标1有序。
第3轮:未排序区间[8,4,5],最小值4,与下标2的8交换,数组变为[2,3,4,8,5]。下标2有序。
第4轮:未排序区间[8,5],最小值5,交换得到最终有序数组。
下面动画演示选择排序完整流程。橙色代表正在扫描比较的元素;红色代表执行交换;绿色代表已经确定的有序元素。
下面是C语言版本选择排序实现。外层循环控制每一轮的未排序起始下标;内层循环遍历未排序区间寻找最小值下标。
#include <stdio.h>
//选择排序函数 升序
void select_sort(int arr[], int n)
{
int i, j;
int min_idx; //保存最小值下标
int temp;
//外层循环:未排序区间起始位置 i
for(i = 0; i < n - 1; i++)
{
min_idx = i; //初始假设未排序第一个元素最小
//内层循环遍历未排序区间找真正最小值下标
for(j = i + 1; j < n; j++)
{
if(arr[j] < arr[min_idx])
{
min_idx = j;
}
}
//把最小值交换到未排序区间头部 i
if(min_idx != i)
{
temp = arr[i];
arr[i] = arr[min_idx];
arr[min_idx] = temp;
}
}
}
int main(void)
{
int arr[] = {5, 3, 8, 4, 2};
int n = sizeof(arr)/sizeof(arr[0]);
select_sort(arr, n);
//输出结果
for(int k=0;k<n;k++)
{
printf("%d ", arr[k]);
}
return 0;
}
min_idx = i:每轮开始默认未排序首元素是最小值;j = i + 1:从i的下一个位置向后扫描寻找更小值;if(arr[j] < arr[min_idx]):发现更小元素,更新最小值下标;if(min_idx != i):只有最小值不在头部,才执行交换;请根据选择排序知识,填写下面代码中的 5 个空。填写完成后点击“提交答案”进行检查。
void select_sort(int arr[], int n)
{
int i,j;
int min_idx;
int temp;
for(i = 0; i < ; i++)
{
min_idx = ;
for(j = i+1; j < n; j++)
{
if(arr[j] arr[min_idx])
{
min_idx = j;
}
}
if(min_idx != i)
{
temp = arr[i];
arr[i] = arr[min_idx];
;
}
}
}
int main()
{
int arr[]={5,3,8,4,2};
int n = ;
select_sort(arr,n);
return 0;
}
n - 1;空2:i;空3:<;空4:arr[min_idx] = temp;空5:sizeof(arr)/sizeof(arr[0])