鼠鼠前面的博客介绍过选择排序是常见的排序算法,选择排序有但不限于直接选择排序和堆排序!那么鼠鼠今天浅谈一下选择排序!
鼠鼠本博客用排升序来介绍选择排序!
目录
1.直接选择排序
1.1.直接选择排序
1.2.直接选择排序特性
2.堆排序
2.1.堆排序
2.2.堆排序特性
3.效率比较
选择排序的基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。
1.直接选择排序
1.1.直接选择排序
1.在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素。
2.若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换。
3.在剩余的array[i]到array[n-2](array[i+1]到array[n-1])集合中,重复上述步骤,直到集合剩余1个元素。
其实说简单点,拿排升序来说:“单趟” 就是遍历需要排序的乱序数组找出最小的数据与第一个数据交换。循环”多趟“在剩余的数据集合中找最小的数据与剩余数据集合的第一个数据交换,直到剩余数据集合数为1停止。
思想很简单,就算鼠鼠解释的不好,相信读者老爷也能明白的,看代码:
1.”单趟“代码(不是直接选择排序完整代码)
int i = begin;
int mini = i;
while (i <= end)
{
if (a[mini] > a[i])
{
mini = i;
}
i++;
}
Swap(&a[mini], &a[begin]);
2.循环控制好begin就能很好控制好数据集合范围,直接选择排序完整代码如下:
void SelectSort(int* a, int begin, int end)
{
while (begin < end)
{
int i = begin;
int mini = i;
while (i <= end)
{
if (a[mini] > a[i])
{
mini = i;
}
i++;
}
Swap(&a[mini], &a[begin]);
begin++;
}
}
我们拉出来试试能不能排好:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
void SelectSort(int* a, int begin, int end)
{
while (begin < end)
{
int i = begin;
int mini = i;
while (i <= end)
{
if (a[mini] > a[i])
{
mini = i;
}
i++;
}
Swap(&a[mini], &a[begin]);
begin++;
}
}
void PrintArrar(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
printf("\n");
}
int main()
{
int a[] = { 7,5,6,1,3,4,2,2 };
PrintArrar(a, sizeof(a) / sizeof(a[0]));
SelectSort(a, 0, sizeof(a) / sizeof(a[0]) - 1);
PrintArrar(a, sizeof(a) / sizeof(a[0]));
return 0;
}
没啥问题!
1.2.直接选择排序特性
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用。
2. 时间复杂度很明显是O(N^2)。
3. 空间复杂度很明显是O(1)。
2.堆排序
2.1.堆排序
堆排序鼠鼠之前浅浅介绍过了,这篇博客介绍过,这里就不介绍了。唯一要注意:排升序要建大堆,排降序建小堆。
我们用堆排序排个升序看看:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//向下调整(大堆)
void AdjustDown(int* a, int parentcoordinate, int HeapSize)
{
int childcoordinate = parentcoordinate * 2 + 1;
while (childcoordinate < HeapSize)
{
if (a[childcoordinate] < a[childcoordinate + 1] && childcoordinate + 1 < HeapSize)
{
childcoordinate++;
}
if (a[parentcoordinate] < a[childcoordinate])
{
Swap(&a[parentcoordinate], &a[childcoordinate]);
parentcoordinate = childcoordinate;
childcoordinate = childcoordinate * 2 + 1;
}
else
{
break;
}
}
}
//堆排序排升序
void HeapSort(int* a, int HeapSize)
{
int i = 0;
//排升序,建大堆(向下调整建堆法)
for (i = (HeapSize - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, i, HeapSize);
}
int end = HeapSize - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, 0, end);
end--;
}
}
int main()
{
int a[] = { 90,80,60,20,40,70,60,30,30,110 };
int Size = sizeof(a) / sizeof(a[0]);
printf("堆排序前:");
for (int i = 0; i < Size; i++)
{
printf("%d ", a[i]);
}
printf("\n");
HeapSort(a, Size);
printf("堆排序后:");
for (int i = 0; i < Size; i++)
{
printf("%d ", a[i]);
}
return 0;
}
确实排好了!
2.2.堆排序特性
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:O(N*logN)。
3. 空间复杂度:O(1)。
3.效率比较
鼠鼠用这两排序来排10w个相同的随机数,大致能看出效率差距:
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
void Swap(int* a, int* b)
{
int tmp = *a;
*a = *b;
*b = tmp;
}
//直接选择排序
void SelectSort(int* a, int begin, int end)
{
while (begin < end)
{
int i = begin;
int mini = i;
while (i <= end)
{
if (a[mini] > a[i])
{
mini = i;
}
i++;
}
Swap(&a[mini], &a[begin]);
begin++;
}
}
//向下调整(大堆)
void AdjustDown(int* a, int parentcoordinate, int HeapSize)
{
int childcoordinate = parentcoordinate * 2 + 1;
while (childcoordinate < HeapSize)
{
if (a[childcoordinate] < a[childcoordinate + 1] && childcoordinate + 1 < HeapSize)
{
childcoordinate++;
}
if (a[parentcoordinate] < a[childcoordinate])
{
Swap(&a[parentcoordinate], &a[childcoordinate]);
parentcoordinate = childcoordinate;
childcoordinate = childcoordinate * 2 + 1;
}
else
{
break;
}
}
}
//堆排序排升序
void HeapSort(int* a, int HeapSize)
{
int i = 0;
//排升序,建大堆(向下调整建堆法)
for (i = (HeapSize - 1 - 1) / 2; i >= 0; i--)
{
AdjustDown(a, i, HeapSize);
}
int end = HeapSize - 1;
while (end > 0)
{
Swap(&a[0], &a[end]);
AdjustDown(a, 0, end);
end--;
}
}
int main()
{
int n = 100000;
int* a = (int*)malloc(sizeof(int) * n);
int* b = (int*)malloc(sizeof(int) * n);
srand((unsigned int)time(0));
for (int i = 0; i < n; i++)
{
a[i] = rand() + i;
b[i] = a[i];
}
int begin1 = clock();
SelectSort(a, 0, n - 1);
int end1 = clock();
printf("SeleckSort:%d\n", end1 - begin1);
int begin2 = clock();
HeapSort(a, n);
int end2 = clock();
printf("HeapSort:%d\n", end2 - begin2);
return 0;
}
我们可以看到在Debug版本下结果:
感谢阅读!