选择排序
基本思想
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完
直接选择排序
- 在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素
- 若它不是这组元素的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
- 在剩余的arrary[i]–array[n-2] (array[i+1]–array[n-1])集合中,重复以上步骤,直到集合剩余一个元素
单纯找一个最大的或最小的有点慢,一次可以同时找出最大的和最小的,最小的下标从0开始,最大的下标从最后一个数开始,不断向内移动
需要注意最大的数可能刚好在最小的数要换过去的位置,这时,数值已经交换,已经不是原来的数,需要更新最大值的下标
void SelectSort(int ary[], int len)
{
//最大数和最小数的下标
int start = 0;
int end = len - 1;
while (start < end)
{
//记录最大数和最小数下标
int mini = start;
int maxi = end;
for (int i = start; i <= end; i++)
{
if (ary[i] < ary[mini])
{
mini = i;
}
if (ary[i] > ary[maxi])
{
mini = i;
}
}
Swap(&ary[start], &ary[mini]);
//最大数在最小值交换过去的位置,更新下标
if (start == maxi)
{
maxi = mini;
}
Swap(&ary[end], &ary[maxi]);
start++;
end--;
}
}
堆排序
基本思想
利用堆设计的排序算法,是选择排序的一种。前提是数组必须已经是堆,所以用原数据建堆,不断替换缩小堆修改数组里元素的位置。排升序建大堆,排降序建小堆
过程
先用向下调整建堆,然后堆顶和数组结尾交换,重新调整堆,直到调整完
```c
//堆排
void AdjustDown(int ary[], int len,int parent)
{
//假设左孩子是最小的
int child = parent * 2 + 1;
while (child < len)
{
//如果右孩子大,更换
if (child + 1 < len && ary[child + 1] > ary[child])
{
child = child + 1;
}
//比孩子小则交换,找出最大的
if (ary[parent] < ary[child])
{
Swap(&ary[parent], &ary[child]);
parent = child;
child = parent * 2 + 1;
}
else
{
break;
}
}
}
void HeapSort(int ary[], int len)
{
//向下调整建堆,i从最后一非叶子结点开始,调整到根
for (int i = (len - 2) / 2; i >= 0; i--)
{
AdjustDown(ary, len, i);
}
//不断替换修改原数组
int end = len - 1;
while (end > 0)
{
//交换之后减少数组大小,调整堆
Swap(&ary[0], &ary[end]);
AdjustDown(ary, end, 0);
end--;
}
}
特性
1.效率高很多
2.时间复杂度:O(N*logN)
3.空间复杂度: O(1)
4.稳定性: 不稳定