基本思想:
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的
数据元素排完 。
直接选择排序
在元素集合array[i]–array[n-1]中选择关键码最大(小)的数据元素
若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
在剩余的array[i]–array[n-2](array[i+1]–array[n-1])集合中,重复上述步骤,直到集合剩余1个元素
交换函数
void swap(int* px , int* py)
{
int tmp = *px;
*px = *py;
*py = tmp;
}
// 选择排序
void SelectSort(int* a, int n)
{
int begin = 0;
int end = n-1;
while(begin<end)
{
int maxi = begin,mini = begin;
//先单趟循环,找最大和最小的
for(int i = begin;i<=end; ++i)
{
if(a[i] < a[mini])
mini = i;
if(a[i] > a[maxi])
maxi = i;
}
//最大最小值与头尾交换
swap(&a[begin],&a[mini]);
// begin == maxi时,最大被换走了,得修正一下maxi的位置
if(begin == maxi)
maxi = mini;
swap(&a[maxi],&a[end]);
//单趟循环
++begin;
--end;
}
直接选择排序的特性总结:
- 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
- 时间复杂度:O(N^2)
- 空间复杂度:O(1)
- 稳定性:不稳定
堆排序
堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
//向下调整
void AdjustDown(int* a, int n, int parent)
{
int child = parent * 2 + 1;
while(child < n)
{
//选出左右孩子中大的那一个
if(child+1 < n && a[child+1] > a[child])
{
++child;
}
// 如果小的孩子大于父亲,则交换,并继续向下调整
if(a[child] > a[parent])
{
swap(&a[child],&a[parent]);
parent = child;
child = parent*2 + 1;
}
else
{
break;
}
}
}
//堆排序
void HeapSort(int* a, int n)
{
//先建大堆,倒着走从最后一个非叶子节点的子树向下调整
for(int i = (n-1-1)/2 ; i >= 0 ; --i)
{
AdjustDown(a, n ,i);
}
int end = n-1;
//找到最大的数据,将最大的数据和最后一个节点数据交换
//之后--end,向下调整一次找到次大的数据,依次循环
while(end > 0)
{
swap(&a[0],&a[end]);
--end;
AdjustDown(a, n ,0);
}
}
直接选择排序的特性总结:
- 堆排序使用堆来选数,效率就高了很多。
- 时间复杂度:O(N*logN)
- 空间复杂度:O(1)
- 稳定性:不稳定