选择排序的思想是假设第一个元素64是一开始的最小元素,找出剩余的5~24的最小的元素(5),如果该元素(5)比64还小,就交换64和该元素(5)就得到了第一次排序结果
紧接着再看64~24的元素,假设64是最小的,找出7~24中最小的元素(6),如果该元素(6)比64还小,就交换该元素(6)和64,就得到了第二次排序结果。
紧接着再对7~89的元素排序,假设元素7是最小的,找出89~24中最小的元素(24),如果该元素(24)比7还小就交换该元素(24)和7,否则不交换得到第三次排序结果
类似的一直做下去
这个排序实现的关键技术点是假定好可能要交换的最小元素,再去找剩余的序列中的最小元素,
如第一次排序前假定64最小,我们用一个下标min记录最小的元素下标,那么min=0,
再从5, 7,89, 6, 24中找出最小的,而且这个元素要比64还小,如果这个元素没有64小的时候我们不做任何事,
等到从5, 7,89, 6, 24找完后,发现元素5是5~24中最小的,而且5还比我们开始假定的64都要小,那么我们
才记住他的下标1(整个数组从下标0开始,a[0]~a[5]对应初始的:64~24),
那就有了代码:
min=0
for(j=1;j<n;j++)
{
if(a[min]>a[j])
{
min=j;
}
}
理想状态(如果a[0]是5.5,当然整个数组得是float了,以后的元素按5,6,7,24,89排列),那么我们紧接着就可以交换元素a[0]和最小元素a[min](a[1]也就是5)
对应代码:
int temp;
temp = a[0];
a[0] = a[min];
a[min] = temp;
别忘了如果我们没找任何比5.5小元素(理想状态的初始元素是5.5, 6, 7, 24,89),那么也犯不着交换元素,只有min的值变了,如果找到了的比初始假定最小元素还小的,
需要修正上面的代码:
/*找出比假定最小元素还小的元素下标*/
min=0
for(j=1;j<n;j++)
{
if(a[min]>a[j])
{
min=j;
}
}
/*找到了比假定最小元素还小的元素,交换元素*/
if(min!=0)
{
int temp;
temp = a[0];
a[0] = a[min];
a[min] = temp;
}
这仅仅只是一轮找寻,我们拿着a[0]去找剩下的a[1]~a[5]中比a[0]值还小的,找出小标,最终方便交换
以上假设只是理想状态,实际我们给出数组明显不能通过一轮找出最小下标,再交换元素就完成排序,
所以,我们需要好多轮这样的查找,而且前一轮查找交换完后,下一轮开始我们就应该,
从剩下的元素开始假定首个元素为最小元素,再从剩下的元素中剔除假定最小元素剩下一个待比较的序列,
再从待比较的序列中找出比假定元素还小的去做前一轮同样工作:
比如第二次排序时我们就从5以外的元素,64~89中假定64最小,从7~24中再找出比64还小的去交换。
这个时候上面代码中的0就应该换1了,同样的下次1就应该换2了,。。。这样看来我们还需要一个外层循环
来控制多轮的最小元素交换,最终排序的代码就诞生了:红色部分代码
代码实现:
#include <stdio.h>
void print_array(int b[],int n)
{
int i;
for(i=0;i<n;i++)
printf("%d ", b[i]);
}
void SelectSort(int b[], int n)
{
int i,j,temp,min;
for(i=0;i<n;i++)
{
min = i;
for(j=i+1;j<n;j++)
{
if(b[j]<b[min])
{
min = j;
}
}
if(min!=i)
{
temp = b[i];
b[i] = b[min];
b[min] = temp;
}
printf("第%d次排序结果:", i+1);
print_array(b,n);
printf("\n");
}
}
int main()
{
int a[]={64,5,7,89,6,24};
int len = sizeof(a)/sizeof(a[0]);
SelectSort(a, len);
printf("最终排序结果:");
print_array(a,len);
return 0;
}
看看运行结果,和图示分析是否一致: