1.直接选择排序
思想:通过一次遍历,找出最大值,和最小值,储存它们的下标,然后将最小值和首位交换,然后将最大值和末位交换,然后将首位向后移动一位,末尾向前移动一位。然后直到首位和末尾相遇时停止,前面为小,后面为大。数组就有序了。
2.代码展示
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
void Swap(int *p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void Print(int* arr, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", arr[i]);
}
printf("\n");
}
SelectSort(int *arr, int n)
{
int left = 0;
int right = n - 1;
int max = 0, min = 0;
while (left < right)
{
for (int i = left; i <= right; ++i) //如果范围不变的话,每次选的最小值和最大值都一样
{
if (arr[i] < arr[min])
{
min = i;
}
if (arr[i] > arr[max])
{
max = i;
}
}
Swap(&arr[left], &arr[min]);
if (max == left)
{
Swap(&arr[min], &arr[max]);
}
else
{
Swap(&arr[right], &arr[max]);
}
++left;
--right;
}
}
int main()
{
int arr[] = {7,4,5,9,8,2,1 };
int n = sizeof(arr) / sizeof(arr[0]);
SelectSort(arr, n);
Print(arr, n);
system("pause");
return 0;
}
3.结果展示
4.复杂度分析
时间复杂度为:O(n2),循环的量级还是在N2。
空间复杂度为:O(1)
5.解题心得
直接选择排序思路非常简单,但是我们需要注意的是,当找到的最小值的下标和末尾下标相同时,或者最大值的下标和首位下标相同时,交换的时候容易出现问题。
例如:先交换最小值时。如果刚刚好最大值的下标是首位。已经把当前位置的值交换走了,那么下次最大值交换的时候,已经不我们要的最大值了。
6.bug修复
void SelectSort(int* arr, int n)
{
int left = 0;
int right = n - 1;
while (left < right)
{
int max = left;
int min = left;
for (int i = left; i <= right; i++)
{
if (arr[i] > arr[max])
max = i;
if (arr[i] < arr[min])
min = i;
}
Swap(&arr[min], &arr[left]);
if (left == max)
{
Swap(&arr[min], &arr[max]);
}
Swap(&arr[max], &arr[right]);
++left;
--right;
}
}
之前的代码没有考虑到第一个就是最小值,那么原地交换后,下一次比较时还和arr[min]比较,它一直是最小的,导致left虚增,所以我们要arr[min]随着范围动起来,保证一定取到范围内的最小值。范围要动,基准比较值也要动。