选择排序(SelectSort)
选择排序的基本思想:刚开始的时候,有序区没有元素,每一趟在无序区中选出来一个最小的元素,然后与无序区第一个元素交换,则此时有序区多一个元素,而无序区少一个元素,知道无序区元素为0结束。
直接选择排序:第一趟排序在R[0..n]中选出一个最小的元素与R[0]交换,第二趟在R[1..n]中选择最小元素,与第一个与R[1]交换,直到无序区的元素只剩下一个排序完成。
以升序为例,假设排序5 7 3 2 0 8 4这组数据
代码实现
void SelectSort(int arr[],int len)
{
int i = 0;
int k = 0;//保存无序区第一个元素下标,方便比较
//一趟确定一个有序区元素,最后一次不用确定,总共len-1次
for (i = 0; i < len - 1; i++)
{
k = i;
int j = 0;
//确定无序区最小元素下标
for (j = i + 1; j < len; j++)
{
if (arr[j] < arr[k])
{
k = j;
}
}
//如果无序区第一个元素为最小,则没有必要交换
if (i != k)
{
int tmp = arr[k];
arr[k] = arr[i];
arr[i] = tmp;
}
}
}
算法优化
上边的算法的思想是一次确定一个有序区的值(最小值),那我们为何不一次确定两个值(一个最小值和一个最大值)呢?这样做肯定效率可以快很多。
代码实现
void SelectSort(int arr[], int len)
{
int left = 0;
int right = len - 1;
while (left < right)
{
int max = left;//记录无序区最大元素下标
int min = left;//记录无序区最小元素下标
int j = 0;
for (j = left + 1; j <= right; j++)
{
//找最大元素下标
if (arr[j] < arr[min])
{
min = j;
}
//找最小元素下标
if (arr[j]>arr[max])
{
max = j;
}
}
//最小值如果是第一个则没有必要交换
if (min != left)
{
int tmp = arr[left];
arr[left] = arr[min];
arr[min] = tmp;
}
//这里很重要,如果最大元素下标是left,前面已经和最小元素交换了,此时最大元素下标应该是min
if (max == left)
{
max = min;
}
//最大值如果是最后一个则没必要交换
if (max != right)
{
int tmp = arr[right];
arr[right] = arr[max];
arr[max] = tmp;
}
left++;
right--;
}
}