选择排序分为两种,分别为直接选择排序和堆排序
先来说明直接选择排序
直接选择排序的思想非常简单,就是在一组数据中先遍历一边数组选出最大的然后往后排,再遍历一边数组,选出次大的,再往后排,以此类推,最后只剩下最小的,排到第一个。这是直接选择排序的思想。
直接选择排序的特性总结:
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
时间复杂度无论什么情况都为N^2;
3. 空间复杂度:O(1)
4. 稳定性:不稳定
代码:
void Swap(int* e1, int* e2)
{
int tmp = *e1;
*e1 = *e2;
*e2 = tmp;
}
void SeloctSort(int* arr, int len)
{
int end = len - 1;
int begin = 0;
int max = 0, min = 0;
//这里用了双指针的方法,使用头尾指针,更方便找最大值最小值
//n趟排序,排升序
while (begin < end)
{
max = begin;
min = begin;
//一趟排序找最大值和最小值,确定头尾
for (int i = begin; i <= end; i++)
{
if (arr[i] < arr[min])
min = i;
else if (arr[i] > arr[max])
max = i;
}
Swap(&arr[min], &arr[begin]);
//如果最大值和最小值是首元素,则最大值的下标与最小值的下标相等,因为前一个交换导致最大值
//下表发生位移
if (max == begin)
{
max = min;
}
Swap(&arr[max], &arr[end]);
begin++;
end--;
}
}
堆排
堆排是利用了二叉树的数据结构思想来进行排序的,首先要建立一个堆,这样才能实现排序。需要注意的是排升序要建大堆,排降序建小堆。
直接选择排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定
void Swap(int* e1, int* e2)
{
int tmp = *e1;
*e1 = *e2;
*e2 = tmp;
}
void AdjustDown(int* a, int n, int parant)
{
int child = parant * 2 + 1;
while (child < n)
{
if ((child + 1 < n) && (a[child] < a[child + 1]))
{
child = child + 1;
}
if (a[parant] < a[child])
{
Swap(&a[child], &a[parant]);
parant = child;
child = parant * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int* arr, int len)
{
//建大堆,采用向下调整建堆
for (int i = (len - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(arr, len, i);
}
int end = len - 1;
//排序,使用向下调整排序,
while (end >= 1)
{
//最后一个与第一个交换,然后寻找是否有比前一个的父亲节点大的,如果没有就是最大的
//Swap交换函数
Swap(&arr[end], &arr[0]);
AdjustDown(arr, end, 0);
end = end - 1;
}
}