C语言:十种排序(七) - 堆排序

2019-08-12  本文已影响0人  lzp1234

前言

一种将无序数组进行排序的方法。

堆排序,wiki参考:
https://zh.wikipedia.org/wiki/%E5%A0%86%E6%8E%92%E5%BA%8F

堆排序,主要思想:将一维数组构造成堆结构,再对堆结构进行排序。

环境

编辑器:vs2019
文件:.c类型

正文

代码参考:

#include <stdio.h>


// 父节点i的左子节点在位置 2i + 1 ;
// 父节点i的右子节点在位置 2i + 2 ;

// 堆排序, 类似于满二叉树。
// 1. 构建大顶堆结构
// 2. 通过大顶堆结构排序


void swap(int* a, int* b) {
    int temp = *b;
    *b = *a;
    *a = temp;
}


// 构建大顶堆, 从小到大排序,父节点大于子节点。
void _max_heap_sort(int source_array[], int start, int end)
{
    // 父节点
    int dad = start;

    // 子节点中最大的节点,默认为左子节点。
    int son = dad * 2 + 1;

    while (son <= end)
    {
        // 找出子节点中最大的
        if (son + 1 <= end && source_array[son + 1] > source_array[son])
        {
            // 如果右子节点大于左子节点,则son 指向右子节点
            son++;
        }

        // 已经找到最大的子节点,开始调整父节点与子节点满足大顶堆。
        if (source_array[son] > source_array[dad])
        {
            swap(&source_array[son], &source_array[dad]);
        }
        dad = son;
        son = dad * 2 + 1;
    }

}


void max_heap_sort_normal(int source_array[], int source_array_length)
{
    int i;
    // 1. 构造大顶堆结构
    // 遍历每一个父节点。大顶堆要求父节点大于子节点,因此采用逆序的方式。
    for (i = source_array_length / 2 - 1; i >= 0; i--)
    {
        _max_heap_sort(source_array, i, source_array_length - 1);
    }

    // 2. 通过大顶堆结构进行排序。
    // 每次都让列表的第一个值最大,然后将最大值移到最后,有点选择排序的意味。
    for (i = source_array_length - 1; i > 0; i--)
    {
        // 将最大值移到末尾
        swap(&source_array[0], &source_array[i]);
        // 将打乱的大顶堆,重新构造。
        _max_heap_sort(source_array, 0, i - 1);
    }
}


int main()
{
    // 生成随机测试列表
    int test_list[20];
    int test_list_length = sizeof(test_list) / sizeof(int);
    printf("测试列表: \n");
    for (int i = 0; i < test_list_length; i++)
    {
        test_list[i] = rand() % 100;
        printf("%d ", test_list[i]);
    }
    printf("\n");

    // 普通堆排序
    max_heap_sort_normal(test_list, test_list_length);
    printf("普通堆排序结果: \n");
    for (int i = 0; i < test_list_length; i++)
    {
        printf("%d ", test_list[i]);
    }
    printf("\n");

    return 0;
}

执行结果参考:


image.png
上一篇下一篇

猜你喜欢

热点阅读