选择排序——选择排序和堆排序

来源:互联网 发布:mac 我的所有文件很乱 编辑:程序博客网 时间:2024/06/05 10:39

常见的比较排序算法有插入排序(直接插入排序和希尔排序),选择排序(选择排序和堆排序),交换排序(冒泡排序和快速排序),归并排序。

还有非比较排序:基数排序和计数排序。

本文讲讲选择排序中的选择排序和堆排序

选择排序

钢结构
以上是选择排序的算法思想,它的时间复杂度为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;    }}
原创粉丝点击