排序(三)-----选择排序and堆排序

直接选择排序
动图:
这里写图片描述
升序:把数组中最大的数与数组最后一个位置的值交换,再在除最后位置以外的数据里里重复上述操作。

void SelectSort(int*arr, int n)//升序
{
    int i;
    for (i = n - 1; i > 0; --i)//选最大数,换到最后面,倒着来
    {
        int max = arr[0];
        int maxindex = 0;
        for (int j = 0; j<=i; ++j)
        {
            if (arr[j] > max)
            {
                max = arr[j];
                maxindex = j;//交换一次,记录max下标
            }
        }
        int tmp = arr[maxindex];
        arr[maxindex] = arr[i];
        arr[i] = tmp;
    }
}

我们可以看到直接选择排序时间复杂度是O(n*n)。它是一种不稳定的排序。

堆排序
有关堆的操作,请参考:小堆的实现
https://blog.csdn.net/vickers_xiaowei/article/details/80353014

用小堆来举例:
动图演示:
这里写图片描述
1、在小堆的基础上,把arr[0]数组的最后一个元素交换;
2、操作的元素个数-1;
3、由于第一步之后,堆不再是小堆,所以向下调整。

把数组调整成最堆,以及每次将元素交换后进行调整的时间复杂度都是O(logN),所以堆排序的时间复杂度为:O(N*logN)。堆排序不稳定。

void Swap(int* a, int*b)
{
    int tmp = *a;
    *a= *b;
    *b = tmp;
}
void Adjustdown(int* arr, int from,int n)//小堆向下调整
{
    int father = from;
    int child = 2 * father + 1;
    while (child<n)
    {
        if (child + 1 < n&&arr[child] > arr[child + 1])
            child++;
        if (child < n&&arr[child] < arr[father])
        {
            Swap(&arr[child], &arr[father]);
            father = child;
            child = 2 * father + 1;
        }
        else
            break;
    }
}

void HeapSort(int* arr, int n)//升序
{
    int FirstNotLeaf = (n - 2) >> 1;//n-1是最后一个结点的下标
    for (int i = FirstNotLeaf; i >= 0; --i)
        Adjustdown(arr, i, n);;// 小堆建成

    int j = n - 1;
    while (j>0)
    {
        Swap(&arr[0], &arr[j]);
        --j;
        Adjustdown(arr, 0, j);
    }
}

有关其它排序:
排序一——直接插入排序and希尔排序
https://blog.csdn.net/vickers_xiaowei/article/details/80613544
排序二——冒泡排序、快速排序三种递归实现and快排非递归
https://blog.csdn.net/vickers_xiaowei/article/details/80646873
排序三——选择排序and堆排序
https://blog.csdn.net/vickers_xiaowei/article/details/80646990
排序四——归并排序和排序结:
https://blog.csdn.net/vickers_xiaowei/article/details/80646992

猜你喜欢

转载自blog.csdn.net/Vickers_xiaowei/article/details/80646990