堆排序

堆的性质(大根堆):父节点大于左右儿子

堆排序

  • 建堆

  • 每次拿堆顶元素和末尾 i 进行交换(相当于 i~n 都是排好序的)。交换后堆顶破坏了堆的性质,把它堆化。

建堆

从最后一个非叶子节点 r 开始,对它记性 s i f t D o w n ( r ) siftDown(r) siftDown(r) 操作,也就是如果它的儿子比它大就交换。如果交换后破坏了儿子为根的堆,那么向下递归。

//siftDown操作相当于维护以r为根的堆
void siftDown(vector<int>& nums, int r, int tail){
    while(leftChild(r)<=tail){
        int biggerId = leftChild(r);
        if(rightChild(r)<=tail && nums[leftChild(r)]< nums[rightChild(r)]){
            biggerId = rightChild(r);
        }
        if(nums[r] >= nums[biggerId]) //该节点稳定了
            break;
        swap(nums,r,biggerId);
        r = biggerId;
    }
}

//从最后一个非叶子节点开始,依次调整以i为根的堆
void buildHeap(vector<int>& nums){
    int last = nums.size()-1;

    for(int i = last/2;i>=0;i--){
        siftDown(nums,i,last);
    }
}
建堆后的排序

每次交换n-1-i和堆顶,然后调整0位根的堆

void sortAfterBuild(vector<int>& nums){
    for(int i=0;i<nums.size();i++){
        int last = nums.size() - i-1;
        swap(nums,0,last);
        siftDown(nums,0,last-1);
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值