来咯来咯,今天弄懂了选择排序,来分享一下。
选择排序核心:从头到尾扫描数组,找到最小的数组元素,和第一个数组元素交换位置,以此类推就得到了一个有序数组。先看动画:
好了,分析完毕看代码:
基础版选择排序
双重循环实现
#include<stdio.h>
void swap(int* a, int* b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
int main()
{
//排序的数据
int array[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
//数组长度
int length = 0;
length = sizeof(array) / sizeof(array[0]);
int i,j,flag;
//排序趟数
for (i = 0; i < length - 1; i++)
{
//记录数组最小元素的下标
flag = i;
for (j = i + 1; j < length; j++)
{
//判断未比较的数组元素中的较小数
if (array[j] < array[flag])
{
//更新最小的数组元素的下标
flag = j;
}
}
//如果最小的数组元素下标不是最开始的记录值,交换数组元素的值
if (flag != i)
{
swap(&array[flag], &array[i]);
}
}
//遍历数组打印数组元素
int m;
for (m = 0; m < length; m++)
{
printf("%d ", array[m]);
}
return 0;
}
递归实现
#include<stdio.h>
void swap(int* a, int* b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
void select_sort(int* array, int length)
{
//递归结束条件
if (length < 2)
{
return;
}
else
{
//递归只关注函数功能实现一次选择排序即可
int flag, j;
flag = 0;
for (j = 0; j < length; j++)
{
//判断数组元素的大小
if (*(array + j) < *(array + flag))
{
//记录数组元素中较小元素的下标
flag = j;
}
}
//如果最小的数组元素不是数组首元素,交换数组元素的值
if (flag != 0)
{
swap(&array[flag], &array[0]);
}
//递归,传入不同的地址即可,完成了依次选择排序,让指针指向下一个数组元素的地址,同时数组长度减一
select_sort(++array, length - 1);
}
}
int main()
{
//排序的数据
int array[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
//数组长度
int length = 0;
length = sizeof(array) / sizeof(array[0]);
//调用函数完成选择排序
select_sort(array, length);
//遍历数组打印数据
int m;
for (m = 0; m < length; m++)
{
printf("%d ", array[m]);
}
return 0;
}
聪明的同学仔细一想,唉,既然对数组元素进行了一次扫描,为啥不把最大值和最小值一起选出来呢?intelligent,那么我们就可以进行优化啦!!看代码:
优化后的选择排序
双重循环实现
#include<stdio.h>
void swap(int* a, int* b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
int main()
{
//排序的数据
int array[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
//数组长度
int length = 0;
length = sizeof(array) / sizeof(array[0]);
int i,j,left,right,min,max;
//初始化开始位置的下标
left = 0;
right = length - 1;
//排序条件
while (left < right)
{
//记录开始最小或最大元素的下标
min = max = left;
for (j = left + 1; j <= right; j++)
{
//判断未比较的数组元素中的较小数
if (array[j] < array[min])
{
//更新最小的数组元素的下标
min = j;
}
//判断未比较数组元素的较大数
if (array[j] > array[max])
{
//更新最大的数组元素的下标
max = j;
}
}
//如果最小的数组元素下标不是最开始的记录值,交换数组元素的值
if (min != left)
{
swap(&array[left], &array[min]);
}
//特例:当最大的那个数组元素的下标恰好是,一次排序开始的最左边元素的下标,因为上面的交
//换使得最大数组元素的下标发生了变化所以,需要再次更新最大数组元素的下标。
if (max == left)
{
max = min;
}
//如果最大的数组元素下标不是最开始的记录值,交换数组元素的值
if (max != right)
{
swap(&array[max], &array[right]);
}
//改变排序的左右下标
left++;
right--;
}
//遍历数组打印数组元素
int m;
for (m = 0; m < length; m++)
{
printf("%d ", array[m]);
}
return 0;
}
递归实现
#include<stdio.h>
void swap(int* a, int* b)
{
int temp;
temp = *b;
*b = *a;
*a = temp;
}
void select_sort(int*array,int length)
{
int min = 0; //记录最小数组元素的下标
int max = 0; //记录最大数组元素的下标
int left = 0; //排序数组最左侧下标
int right = length - 1; //排序数组最右侧下标
//递归终止条件
if (length < 2)
{
return;
}
else
{
int j;
//排序的循环
for (j = 1; j < length; j++)
{
//判断未比较的数组元素中的较小数
if (array[j] < array[min])
{
//更新最小的数组元素的下标
min = j;
}
//判断未比较的数组元素中的较大数
if (array[j] > array[max])
{
//更新最大的数组元素的下标
max = j;
}
}
//如果最小的数组元素下标不是最开始的记录值,交换数组元素的值
if (min != left)
{
swap(&array[min], &array[left]);
}
//特例:当最大的那个数组元素的下标恰好是,一次排序开始的最左边元素的下标,因为上面的交
//换使得最大数组元素的下标发生了变化所以,需要再次更新最大数组元素的下标。
if (max == left)
{
max = min;
}
//如果最大的数组元素下标不是最开始的记录值,交换数组元素的值
if (max != right)
{
swap(&array[max], &array[right]);
}
}
//修改函数实参,调用一次函数得到了最大值,最小值,所以减去2
length -= 2;
//改变指针指向数组元素的位置
select_sort(++array, length);
}
int main()
{
//排序的数据
int array[15] = { 3,44,38,5,47,15,36,26,27,2,46,4,19,50,48 };
//数组长度
int length = 0;
length = sizeof(array) / sizeof(array[0]);
select_sort(array, length);
int i;
for (i = 0; i < length; i++)
{
printf("%d ", array[i]);
}
return 0;
}
好啦今天的选择排序就到这里了,写代码挺有意思的,期待明天的希尔排序。。
加油同志们!!!!!!!!