十大排序之堆排序

堆排序

视频讲解

堆排序讲解
在这里插入图片描述

预备知识

堆排序

堆排序是利用堆这种数据结构而设计的一种排序算法,堆排序是一种选择排序,它的最坏,最好,平均时间复杂度均为O(nlogn),它也是不稳定排序。首先简单了解下堆结构。

堆是具有以下性质的完全二叉树:每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。如下图:
在这里插入图片描述
同时,我们对堆中的结点按层进行编号,将这种逻辑结构映射到数组中就是下面这个样子
在这里插入图片描述
该数组从逻辑上讲就是一个堆结构,我们用简单的公式来描述一下堆的定义就是:

大顶堆:arr[i] >= arr[2i+1] && arr[i] >= arr[2i+2]

小顶堆:arr[i] <= arr[2i+1] && arr[i] <= arr[2i+2]

基本思想:

堆排序的基本思想是:将待排序序列构造成一个大顶堆,此时,整个序列的最大值就是堆顶的根节点。将其与末尾元素进行交换,此时末尾就为最大值。然后将剩余n-1个元素重新构造成一个堆,这样会得到n个元素的次小值。如此反复执行,便能得到一个有序序列了

#include<iostream>
#include<vector>
using namespace std;

void heapify(vector<int>& nums, int n, int i) {   //n:数组长度 i:当前索引
    if(i > n) return;
    int c1 = 2 * i + 1;
    int c2 = 2 * i + 2;
    int max = i;
    if(c1 < n && nums[c1] > nums[max]) {
        max = c1;
    }
    if(c2 < n && nums[c2] > nums[max]) {
        max = c2;
    }  //两个if 找出最大值的索引
    if(max != i) {
        swap(nums[max], nums[i]);
        heapify(nums, n, max);   
    }
}

void heapify_build(vector<int>& nums, int n) { ///建立大根堆,从树的倒数第二层第一个结点开始,对每个结点进行heapify操作,然后向上走
     int temp = (n - 2) / 2;
     for(int i = temp; i >= 0; i--) {
         heapify(nums, n, i);
     }
    // for(int i = 0; i < nums.size(); i++) {
       //  cout<<nums[i]<<endl;
     }
}

void heapify_sort(vector<int> &nums, int n) {  
//建立大根堆之后,每次交换最后一个结点和根节点(最大值),对交换后的根节点继续进行heapify(此时堆的最后一位是最大值,因此不用管他,n变为n-1)
     heapify_build(nums, n);
     for(int i = 0; i < n; i++){
         swap(nums[0], nums[n-1-i]);  //将最大值提出来放到最后
         heapify(nums, n-1-i, 0);
     }
}

int main() {
    vector<int> nums = {10,8,4,6,9,10,123,6,2,14,3,8,5};
    int len = nums.size();
    heapify_sort(nums, len);
    for(auto &i : nums) {
        cout<<i<<endl;
    }
    return 0; 
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值