选择排序
选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。
唯一的好处可能就是不占用额外的内存空间了吧。
1. 算法步骤
-
首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置。
-
再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。
-
重复第二步,直到所有元素均排序完毕。
2. 动图演示
3.代码实现
void swap(int* a, int* b)//该函数的作用是进行交换,针对int类型的变量
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
void selection_sort(int arr[], int len)//默认是对int类型的数组进行数据交换
{
int pos = 0;//指示数组中当前遍历中最小元素
for (int i = 0; i < len - 1; i++)
{
pos = i;
for (int j = i + 1; j < len; j++)
{
if (arr[pos] > arr[j])
{
pos = j;//标记这次迭代中数据元素最小的位置
}
}
swap(arr + i, arr + pos);
}
}
void main()
{
int arr[] = { 22, 34, 3, 32, 82, 55, 89, 50, 37, 5, 64, 35, 9, 70 };//定义一个待排序的数组
int len = sizeof(arr) / sizeof(*arr);//获取数组的大小
printf("\nsort before\n");
for (int i = 0; i < len; i++)//打印排序前数组元素
{
printf("%d\t",arr[i]);
}
selection_sort(arr, len);//对数组进行排序,数组长度为len
printf("\nsort after\n");
for (int i = 0; i < len; i++)//打印排序后数组元素
{
printf("%d\t",arr[i]);
}
system("pause");
}
4.改进版本
4.1.疑问
不妨试想一下,对一个升序的数组进行排序操作,所需要的次数是多少?
为了测试次数,更改之后的代码为:(创建一个变量来记录循环处理的次数)
void selection_sort(int arr[], int len)//默认是对int类型的数组进行数据交换
{
int pos = 0;//指示数组中当前遍历中最小元素
for (int i = 0; i < len - 1; i++)
{
pos = i;
for (int j = i + 1; j < len; j++)
{
count++;//用于计算运行的总次数,只是为了测试,不加这个语句也是可以的
if (arr[pos] > arr[j])
{
pos = j;//标记这次迭代中数据元素最小的位置
}
}
swap(arr + i, arr + pos);
}
}
结果如下:
一个已经排序完成的数组再次进行排序却还要进行55次。难道不觉得这个算法有问题吗?
4.2.解析
无论待排序的数组中数据元素的顺序如何,排序的总次数是不会改变的。总次数与数组的大小如下。
sum=len∗(len−1)/2
sum = len*(len-1)/2
sum=len∗(len−1)/2
sum : 排序的总次数 len:数组长度 😄
4.3.解决方案
void selection_sort_advance(int arr[], int len)//默认是对int类型的数组进行数据交换
{
int pos = 0;//指示数组中当前遍历中最小元素
int flag = false;
for (int i = 0; i < len-1; i++)
{
pos = i;
flag = false;
for (int j = i+1; j < len; j++)
{
count++;
if (arr[pos] > arr[j])
{
pos = j;
flag = true;
}
}
if (flag == false)
{
return;
}
swap(arr + i, arr + pos);
}
}
结果如下:
4.4.性能对比
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
void swap(int* a, int* b)
{
int temp;
temp = *a;
*a = *b;
*b = temp;
}
int count = 0;
void selection_sort_advance(int arr[], int len)//默认是对int类型的数组进行数据交换
{
int pos = 0;//指示数组中当前遍历中最小元素
int flag = false;
for (int i = 0; i < len-1; i++)
{
pos = i;
flag = false;
for (int j = i+1; j < len; j++)
{
count++;
if (arr[pos] > arr[j])
{
pos = j;
flag = true;
}
}
if (flag == false)
{
return;
}
swap(arr + i, arr + pos);
}
}
void selection_sort(int arr[], int len)//默认是对int类型的数组进行数据交换
{
int pos = 0;//指示数组中当前遍历中最小元素
for (int i = 0; i < len - 1; i++)
{
pos = i;
for (int j = i + 1; j < len; j++)
{
count++;
if (arr[pos] > arr[j])
{
pos = j;
}
}
swap(arr + i, arr + pos);
}
}
void main()
{
int arr[] = { 5,3,4,1,2,0,6,7,8,9,10,11,12 };//定义一个待排序的数组
int arr1[] = { 5,3,4,1,2,0,6,7,8,9,10,11,12 };//定义一个待排序的数组
int len = sizeof(arr) / sizeof(*arr);
printf("\nsort before\n");
for (int i = 0; i < len; i++)
{
printf("%d\t", arr[i]);
}
selection_sort(arr,len);
printf("\nselection_sort after\n");
for (int i = 0; i < len; i++)
{
printf("%d\t", arr[i]);
}
printf("\nselection_sort:%d\n", count);
count = 0;//清除selection_sort函数处理的次数
selection_sort_advance(arr1, len);
printf("\nselection_sort_advance after\n");
for (int i = 0; i < len; i++)
{
printf("%d\t", arr1[i]);
}
printf("\nselection_sort_advance:%d\n", count);
system("pause");
}