文章目录
- 选择排序
- 1.直接选择排序
- 优化直接选择排序
- 2. 堆排序
选择排序
基本思想
选组排序是从待排序数据中选出最大/最小的元素放入到序列的起始位置,直到待排序数据全部有序。
直接选择排序和堆排序的基本思想均符合选择排序。
1.直接选择排序
假设数据按升序排序
基本步骤
- 在待排序数据arr[i]-arr[n-1]中选出最小元素
- 如果选出的min不处于待排数据第一个位置时,交换min与arr[i]
- 重复上述操作直至待排序数据全部有序
下面动图演示直接选择排序
代码
void SelectSort(int* arr, int sz)
{
int left = 0;
while (left < sz - 1)
{
int minPos = left;//每次将待排序数组第一个元素设置为最小值
//选出待排序数据中最小值
for (int i = left; i < sz; i++)
{
if (arr[i] < arr[minPos])
{
minPos = i;
}
}
//交换最小值和arr[left]的位置
if (minPos != left)
Swap(arr[minPos], arr[left]);
//更新待排序数据
left++;
}
}
注意
这里Swap函数参数使用的是C++的引用,所以不需要传地址
优化直接选择排序
直接选择排序是从一边开始排序,优化后的选择排序可以一趟选出最大值和最小值
最小值放在待排序数组第一个位置,最大值放在待排序数组最后一个位置,从两头开始排序。
void SelectSort(int* arr, int sz)
{
int left = 0;
int right = sz - 1;
while (left < right)
{
int minPos = left;
int maxPos = left;
//选出待排序区间最值
for (int i = left; i <= right; i++)
{
if (arr[minPos] > arr[i])
minPos = i;
if (arr[maxPos] < arr[i])
maxPos = i;
}
//最大值放在区间末尾
Swap(arr[maxPos], arr[right]);
//如果最小值在末尾,修正最小值
if (minPos == right)
minPos = maxPos;
//最小值放在区间首部
Swap(arr[minPos], arr[left]);
//更新待排序区间
left++;
right--;
}
}
直接选择排序性能分析:
- 无论是直接选择排序还是优化后的直接选择排序时间复杂度都是 O ( n 2 ) O(n^2) O(n2)
- 空间复杂度均为 O ( 1 ) O(1) O(1)
- 不稳定
- 实际生活中很少使用直接选择排序,效率低
2. 堆排序
堆排序是根据堆这种数据结构设计的一种算法,他是选择排序的一种。
堆排序的基本思想
- 将待排序数据构建为堆
- 交换堆顶元素和最后一个元素
- 对堆进行调整使之满足堆的性质
- 重复上述过程直至所有元素均有序
代码实现
void AdjustDown(int* a, int sz, int parent)
{
int child = parent * 2 + 1;
while (child < sz)
{
//大堆逻辑-->排升序
if (child + 1 < sz && a[child] < a[child + 1])
child++;
if (a[parent] < a[child])
{
Swap(a[parent], a[child]);
parent = child;
child = child * 2 + 1;
}
else
break;
}
}
void HeapSort(int* arr, int sz)
{
//向下建大堆-->排升序
for (int i = (sz - 2) / 2; i >= 0; i--)
AdjustDown(arr, sz, i);
//排序
int end = sz - 1;
while (end > 0)
{
Swap(arr[0], arr[end]);
AdjustDown(arr, end, 0);
end--;
}
}
关于堆排序详细解释请移步堆的应用