堆排序

堆排序

健堆原理:
利用一段连续的数组空间实现逻辑上的堆。
主要根据完全二叉树的父子节点间的关系,当根节点从0开始时,其父节点i对应的左孩子是 2 * i + 1, 右孩子是2 * i + 2。 相应的子节点i对应的父节点为 (i - 1)/2
push一个元素
(1)插入元素,在末尾插入,每次向上调整 (大根堆)

void shift_up(int ind) {     //从下标i开始向上调整
    while(ind && data[(ind - 1) / 2] < data[ind]) {
        swap(data[(ind - 1) / 2], data[ind]);
        ind = (ind - 1) / 2;
    }
    return;
}

弹出一个元素(最值)
(2)弹出元素,在首部弹出,然后将最后一个元素交换上来,向下调整,流程是先把根节点和左孩子比较,记录较大的位置,然后将其和右孩子比较,记录最大的值的位置,然后交换根节点和最大的值。

void shift_down(int ind) {
    int n = cnt - 1;  //最大值
    while (ind * 2 + 1 <= n) {   //确保其左孩子在范围内
        int temp = ind;
        if (data[temp] < data[ind * 2 + 1]) temp = ind * 2 + 1;
        if (ind * 2 + 2 <= n && data[temp] < data[ind * 2 +  2]) temp = ind * 2 + 2;   
//此时temp记录最大值的位置
        if (temp == ind) break;
        swap(data[temp], data[ind]);
        ind = temp;
    }
    return;
}

堆排序思路:
三部分:
1、向下调整,shift_down(int ind)
2、从n/2位置开始,循环向下调整,建堆
3、交换第一个和最后一个位置,从1位置继续向下调整,
根据数组建立初始大顶堆的过程:从最后一个非叶子节点开始,不断向下调整
然后将每次大顶堆的第一个元素放到数组末尾,继续从根节点向下调整
所以只需要手写一个向下调整的函数。

堆排算法

void HeapSort(int *a, int length) {
    for (int i = length / 2 - 1; i >= 0; i--) {  //建堆
        shift_down(a, i, length);
    }
    for (int i = length -1; i > 0; i--) {  //排序
        swap(a[0], a[i]);   //每次交换一个数,将最大值放到最后
        shift_down(a, 0, i);   //继续对0位置向下调整
    }

    return;
}

向下调整

void shift_down(int *a, int ind, int cnt1) {  //cnt1代表堆顶元素个数
    int n = cnt1 - 1;
    while (ind * 2 + 1 <= n) {  //确保不超过堆顶位置
        int temp = ind;
        if (a[temp] < a[ind * 2 + 1]) temp = ind * 2 + 1;
        if (ind * 2 + 2 <= n && a[temp] < a[ind * 2 +  2]) temp = ind * 2 + 2;
        if (temp == ind) break;
        swap(a[temp], a[ind]);
        ind = temp;
    }
    return;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值