目录
为了讲解方便,以下排完序后,统一为升序
1 选择排序
1.1 原理
核心思想是通过不断地选择未排序序列中的最小元素,然后将其放到已排序序列的末尾(或未排序列的起始位置)。
1.2 具体步骤
1. 初始状态:所有元素初始都为未排序状态
2 在未排序元素中,找到最小的那个元素的下标
3 与未排序的第一个元素(已排序的末尾元素)交换位置
4 循环 2 ~ 3,直到所有元素都变为已排了的元素
1.3 代码实现
代码实现的关键点:找下标,换位置,以及循环条件。同时也是容易出错的点。
#include<stdio.h>
void sort(int* p, int n)
{
for (int i = 0; i < n - 1; i++) // < n 也可以,只是无意义的重复,效率更低
{
int min = i; // 找出的最小值,最后要放的位置的下标
int j = i;
for (j = i + 1; j < n; j++) // 可以=i,只是=i,无意义。
{
if (p[min] > p[j])
min = j;
// for循环结束后,j会++
if (n - 1 == j)
break;
}
// 交换数据
int temp = p[i];
p[i] = p[min];
p[min] = temp;
}
}
int main()
{
int arr[] = { 9,6,8,-1,0,5,2,8 };
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, sz); // 选择排序
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}
1.4 优化
原来一趟只找出最小值,现在一趟既找出最小值,也找出最大值,循环的次数就减半了。
#include<stdio.h>
void swap(int* a, int* b)
{
int temp = *a;
*a = *b;
*b = temp;
}
void sort(int* p, int n)
{
// 循环趟数减半,可以了就要停止,不然就会继续换,反而无序
for (int i = 0; i <= n / 2 + 1; i++)
{
int min = i; // 找出的最小值的下标
int max = n -i - 1; // 找出的最大值的下标
int j = i;
for (j = i; j < n - i; j++)
{
if (p[min] > p[j])
min = j;
if (p[max] < p[j])
max = j;
if (n - 1 - i == j)
break;
}
// 交换数据
// 当最小值与最大值恰好位置相反,换两次=没换
if (!(p[min] == p[n - 1 - i] || p[i] == p[max]))
{
swap(&p[i], &p[min]);
swap(&p[n - 1 - i], &p[max]);
}
else
{
swap(&p[i], &p[n - 1 - i]);
}
}
}
int main()
{
int arr[] = { 9,6,8,-1,0,5,2,8 };
int sz = sizeof(arr) / sizeof(arr[0]);
sort(arr, sz); // 选择排序优化
for (int i = 0; i < sz; i++)
{
printf("%d ", arr[i]);
}
return 0;
}