堆排序介绍(C语言)

算法简介

        堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。通常堆是通过一维数组来实现的。在数组起始位置为0的情形中:

父节点i的左子节点在位置:2i+1

父节点i的右子节点在位置:2i+2

子节点i的父节点在位置:(i-1)/2

算法思想

        首先将待排序的数组构造成一个大根堆,此时,整个数组的最大值就是堆结构的顶端。将顶端的数与末尾的数交换,此时,末尾的数值为最大值,剩余待排序数组个数为n-1。将剩余除末尾外的n-1个数再构造成大根堆,再将顶端数与n-1位置的数交换,如此反复执行,便能得到有序数组。

堆操作   

最大堆调整(Max_Heapify):将堆的末端子节点作调整,使得子节点永远小于父节点

创建最大堆(Build_Max_Heap):将堆所有数据重新排序

堆排序(HeapSort):移除位在第一个数据的根节点,并做最大堆调整的递归运算

代码实现

最大堆调整

void Heapify(int *num, int len, int k)
{
    if (k < len)
    {
        int root = k;           // 根结点
        int lchild = 2*k + 1;   // 左孩子结点
        int rchild = 2*k + 2;   // 右孩子结点
        // 查找左右孩子结点中的最大结点
        if (lchild < len && num[root] < num[lchild])
        {
            root = lchild; 
        }
        if (rchild < len && num[root] < num[rchild])
        {
            root = rchild;
        }
        // 交换最大结点到根结点
        if (root != k)
        {
            num[root] ^= num[k];
            num[k] ^= num[root];
            num[root] ^= num[k];
            // 对交换后的孩子结点子树进行最大堆调整
            Heapify(num, len, root);
        }
    }
}

堆排序 

void CreateHeap(int *num, int len)
{
    int i;// 最后一个结点下标
    int last = len - 1;// 最后一个结点的父结点下标     
    int father = (last - 1) / 2;
    // 从最后一个结点的父结点到根结点,依次进行最大堆调整
    for (i = father; i >= 0; i--)
    {
        Heapify(num, len, i);
    }
}
void HeapSort(int *num, int len)
{
    CreateHeap(num, len);
    int i;
    for (i = len - 1; i >= 0; i--)
    {
        // 将最大堆的根结点换到最后一个结点
        num[i] ^= num[0];
        num[0] ^= num[i];
        num[i] ^= num[0];
        Heapify(num, i, 0);//对根结点做最大堆调整,只考虑最大孩子的分支(末尾结点不调整)
    }   
}

 主函数部分调用函数

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define size 10
int main(int argc, char *argv[])
{
    int i;
    int num[size] = {8, 21, 13, 16, 7, 33, 21, 10, 1, 5};
    printf("调整前:");
    for (i = 0; i < size; i++)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
    HeapSort(num, size);
    printf("调整后:");
    for (i = 0; i < size; i++)
    {
        printf("%d ", num[i]);
    }
    printf("\n");
    return 0;
}

 排序结果

YX@ubuntu:~/2207/sj$ ./a.out
调整前:8 21 13 16 7 33 21 10 1 5 
调整后:0 5 7 8 10 13 16 21 21 33 

时间复杂度

        平均时间复杂度:O(nlogn),不稳定。

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值