选择排序
基本思想:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完 。
1.直接选择排序
- 首先在未排序序列中找到最小(大)元素(看你是排升序还是降序),存放到排序序列的起始位置。
- 再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的后面。
- 重复第二步,直到所有元素均排序完毕。
实现代码:
其中a为待排序的数组,n为元素个数
void SelectSort(int* a, int n)
{
int begin = 0;//开始元素的坐标
int min = 0;//假设最小元素的坐标
while (begin<n)
{
min = begin;//注意下一次进来要更新坐标
for (int i = begin+1; i < n; i++)
{
if (a[i] < a[min])
{
min = i;
}
}
Swap(&a[begin], &a[min]);
begin++;
}
}
直接选择排序的特性总结:
1.直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O( N 2 N^2 N2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定
2.堆排序
——对于堆有不理解的老铁可以看这篇文章(C语言)数据结构二叉树之堆
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
堆排序即利用堆的思想来进行排序,总共分为两个步骤:
- 建堆 (升序建大堆 ,降序建小堆)
- 利用堆删除思想来进行排序
解释:由于堆的特殊特性堆顶元素一定是最大的或者最小的,让堆顶先与下标为n-1的元素交换,交换完再进行向下调整;让堆顶再与下标为n-2的元素交换,交换完再进行向下调整;让堆顶再与下标为n-3的元素交换,交换完再进行向下调整,就这个过程循环往复,直到把下标为1的元素和下标为0的元素交换完成之后停止,堆排序就排好了。
实现代码:
void Swap(int* p1, int* p2)
{
int tmp = *p1;
*p1 = *p2;
*p2 = tmp;
}
void AdjustDown(int* a, int n, int parent)
{
int minChild = parent * 2 + 1;
while (minChild < n)
{
// 找出小的那个孩子
if (minChild + 1 < n && a[minChild + 1] > a[minChild])
{
minChild++;
}
if (a[minChild] > a[parent])
{
Swap(&a[minChild], &a[parent]);
parent = minChild;
minChild = parent * 2 + 1;
}
else
{
break;
}
}
}
// O(N*logN)
void HeapSort(int* a, int n)
{
// 大思路:选择排序,依次选数,从后往前排
// 升序 -- 大堆
// 降序 -- 小堆
// 建堆 -- 向下调整建堆 - O(N)
for (int i = (n - 1 - 1) / 2; i >= 0; --i)
{
AdjustDown(a, n, i);
}
// 选数 N*logN
int i = 1;
while (i < n)
{
Swap(&a[0], &a[n - i]);
AdjustDown(a, n - i, 0);
++i;
}
}
直接选择排序的特性总结:
1. 堆排序使用堆来选数,效率就高了很多。
2. 时间复杂度:最好情况和最坏情况都是O(N*logN)
3. 空间复杂度:O(1)
4. 稳定性:不稳定