常见的比较排序算法有插入排序(直接插入排序和希尔排序),选择排序(选择排序和堆排序),交换排序(冒泡排序和快速排序),归并排序。
还有非比较排序:基数排序和计数排序。
本文讲讲选择排序中的选择排序和堆排序
选择排序
以上是选择排序的算法思想,它的时间复杂度为O(N的平方)。
代码实现:
void SelectSort(int* a, size_t n)
{
assert(a);
size_t begin = 0;
size_t end = n - 1;
while (begin < end)
{
int min = begin;
for (size_t i = begin; i <= end; i++)
{
if (a[i] < a[min])
{
min = i;
}
}
swap(a[min], a[begin]);
begin++;
}
}
通过上面的我们可以看到我们用min记录小的,然后与begin进行交换,
那么我们就可以进行优化用max记录大的,然后与end进行交换。
下面是优化版本:
上图是选择排序的优化版本,它的时间复杂度是O(N)
代码实现:
//优化版本,同时找到最大的和最小的
void SelectSort(int* a, size_t n)
{
assert(a);
size_t begin = 0;
size_t end = n - 1;
while (begin < end)
{
int min = begin;
int max = begin;
for (size_t i = begin; i <= end; ++i)
{
if (a[min] > a[i])
{
min = i;
}
if (a[max] < a[i])
{
max = i;
}
}
swap(a[min], a[begin]);
if (max == begin)
{
max = min;
}
swap(a[max], a[end]);
++begin;
--end;
}
}
堆排序:
void AdjustDown(int* a, size_t root, size_t n)
{
int parent = root;
int child = 2 * parent + 1;
while (child < n)
{
if ((child + 1) < n && a[child + 1] > a[child])
{
++child;
}
if (a[parent] < a[child])
{
swap(a[parent], a[child]);
parent = child;
child = 2 * parent + 1;
}
else
{
break;
}
}
}
void HeapSort(int* a, size_t n)
{
assert(a);
for (int i = (n - 2) / 2; i >= 0; --i)
{
AdjustDown(a, i, n);
}
size_t end = n - 1;
while (end > 0)
{
swap(a[0], a[end]);
AdjustDown(a, 0, end);
--end;
}
}