【C-排序算法】堆排序

原理


核心思想:利用堆数据结构的特点


大根堆的特点

  1. 形状特征:完全二叉树(顺序存储的)
  2. 数值特征:对于每一个子树而言,根大于左孩子且大于右孩子

堆排序的步骤,n为数据规模

  1. 对n个数建大根堆
  2. 把堆顶放在最后一个位置
  3. 减少数据规模,再对n-1个数建大根堆
  4. 重复2和3,直到数据规模为1时

具体排序步骤: 对N个数建立大根堆

  1. 从最后一个父节点(编号为N/2,下标为N/2-1)开始建堆,直到堆顶(编号为1,下标为0)
    1. 先父节点下的兄弟节点比较(选出大的)
    2. 再父子比较,如果父比子小就交换并向下循环,如果父节点大退出循环
  2. 堆顶放最后,缩减堆的规模
  3. 循环建堆(从堆顶开始,建完后堆顶放最后,缩减堆的规模,直到堆的规模为1)

性能


时间复杂度:O(n * logn)【建堆需要O(n),调整堆需要O(n * logn)】

空间复杂度:O(1)



代码


输入:数组地址,数组长度

输出:升序排列的数组


heap_sort.c

//如果换成字符串类型的数组,那么除了修改元素类型外,涉及到比较操作和交换操作的地方,全部都要改成字符串形式的               
//如果不是字符串类型的,只需修改类型即可

void adjust_maxheap(int *arr, int pos, int len)
{
    //根据父节点的下标,求出子节点的下标
    int dad = pos;
    int son = 2 * pos + 1;

    while (son < len) {
        if (son + 1 < len && arr[son + 1] > arr[son]) {
            //如果右孩子存在,且大于左孩子,更新孩子节点
            son = son + 1;
        }

        if (arr[son] > arr[dad]) {
            //如果子节点大于父节点,交换父子节点
            int tmp = arr[son];
            arr[son] = arr[dad];
            arr[dad] = tmp;

            //更新父子节点,向下循环,调整堆
            dad = son;
            son = 2 * dad + 1;
        }
        else {
            //父节点大于子节点,符合大根堆,退出
            break;
        }
    }
}

void heap_sort(int *arr, int len)
{
    //堆的规模小于2,不用排序
    if (2 > len) {
        return;
    }

    //从最后一个父节点开始,建立大根堆,直到首节点
    for (int i = len / 2 - 1; i >= 0; --i) {
        adjust_maxheap(arr, i, len);
    }

    //堆顶放最后
    int tmp = arr[0];
    arr[0] = arr[len - 1];
    arr[len - 1] = tmp;

    //不断缩减堆的规模,重建堆,找出当前规模的最大值
    for (int size = len - 1; size >= 1; --size) {
        adjust_maxheap(arr, 0, size);
        //建好大根堆后,堆顶放最后
        int tmp = arr[0];
        arr[0] = arr[size - 1];
        arr[size - 1] = tmp;
    }
}
  • 9
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值