堆排序

一般用数组来表示堆,下标为 i 的非根结点的父结点下标为(i-1)/2。下标为 i 的左右子结点分别为 (2i + 1)、(2i + 2)

构建堆的思路:

n个元素的数组能划分成n/2个子堆进行管理和调整,从下往上调整,但下面的子堆可能受上面的堆调整的影响,是否需要调整子堆,要看移动的结点是否为“叶结点”,或者说是否有左右子结点

各个子堆调整。为保持根是最大/最小值,与子结点执行交换操作

受影响的下级堆。先判断以被交换的子节点为根的下级堆是否被破坏,是,就重新调整,并再判断下下级堆有无被破坏,一直进行维护,直到做了交换的子结点无子结点为止

void adjMaxHeap2(int* a, int len, int root) {
    int temp = a[root];
    for (int i = root * 2+1; i < len; i=i*2+1) {//下标
        if (i+1 < len && a[i + 1] > a[i])i++;
        if (a[i] > temp) {
            a[root] = a[i];//就算交换了也是temp成为新的root,再和子节点比较
            root = i;
        }
        else break;
    }
    a[root] = temp;
}
void adjMaxHeap(int* a, int len, int root) {
    int j, temp = a[root];
    for (int i = root * 2 + 1; i < len; i = i * 2 + 1) {//下标
        if (i + 1 < len && a[i + 1] > a[i])i++;//大根堆
        if (a[i] > a[root]) {//大根堆
            swap(a[root], a[i]);//不一定要交换
            root = i;//下级堆可能受影响
        }
        else break;
    }
}
void heapSort(int* a, int len) {
    //下标0
    for (int i = len / 2 - 1; i >= 0; i--) adjMaxHeap(a, len, i);//到这里只是建立了大根堆
    for (int i = len - 1; i > 0; i--) {//把堆转为升序序列,找len-1次最大值
        swap(a[0], a[i]);//把最大值移到最后
        adjMaxHeap(a, i, 0);//除去最大值,重新选出次最大值
    }
}
void test02() {
    //sizeof(a) / sizeof(*a)
    int a3[] = { 49,38,65,97,76,13,27,49 };
    int a5[] = { 15,1,2,3,5,8,4,9,6,7 };
    int a2[] = { 1,2,3,4,5,7,8,9,10,6 };
    int a4[] = { 1,2,3,4,5,7,8,9,10,6 };
    int a6[] = { 8,3,6,4,2,1,5,7,9,10,12,11 };
    int a[] = { 16,9,20,15,3,18,13,2,17,10,5,7,11,12,6,1,19,4,8,14 };
    heapSort(a, sizeof(a) / sizeof(*a));
    

    for (const int i : a)cout << i << ' '; cout << endl;

}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值