堆排序算法原理及C++实现(详细注释)

1、算法原理
原理部分参考下面这个博客即可:
堆排序算法(图解详细流程)

2、C++实现:

解法一:利用vector实现最大堆
注意:heap_max这个函数调用了两次: 建堆时候和交换最大值之后分别调用一次:

//注意:是把一个数组想象成了最大堆!!!!!!
//利用最大堆这种数据结构进行排序:先构建个最大堆,
//然后将根节点与数组最后一个元素交换,然后对剩下的N-1个元素进行迭代(建堆、交换)
void heap_sort(vector<int> &input)
{
    //build_heap(input);

    // 1、先建堆!!!!!!!
        //从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
    for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
                                       //其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
    {
        heap_max(input,i,input.size()); //建堆时候这个参数n(第三个参数)一直不变,但是i在变
    }
    ///2、把最大元素移除  接着进行见堆!!!!
    for(int j=input.size()-1;j>0;j--) //这里的j是大于0   没有等于
    {
        // 将根节点(最大值)与数组待排序部分的最后一个元素交换,这样最终得到的是递增序列
        int temp;
        temp = input[0];
        input[0] = input[j];
        input[j] = temp;
        // 待排序数组长度减一,只要对换到根节点的元素进行排序,将它下沉就好了。
        heap_max(input,0,j);  //这个时候i这个参数不变,但是参数n(j)一直在变
    }
}
// void build_heap(vector<int> &input) //构建最大堆
// {
//     //从第一个非叶子节点开始调整的原因在于叶子节点没有孩子,那么显然它也就满足堆的性质,也就没有调整的必要了。
//     for(int i=input.size()/2-1;i>=0;i--)//根节点为0,最后一个叶节点的下标为n-1,
//                                        //其父节点是第一个非叶节点,下标为((n-1)-1 )/ 2 = (n-2)/2 = n/2 - 1
//     {
//         heap_max(input,i,input.size());
//     }
// }
void heap_max(vector<int> &input, int i,int n)//将i节点为根的堆中大的数依次上移,n表示堆中的数据个数
{
    int left = 2*i+1;  // i节点的左孩子
    int right = 2*i+2;   // i节点的右孩子
    int largest = i; //先设置父节点和子节点三个节点中最大值的位置为父节点下标
    if(left<n&&input[left]>input[largest])
    {
        largest = left;
    }
    if(right<n&&input[right]>input[largest])
    {
        largest = right;
    }
    if(largest!=i)  //最大值不是父节点,则进行交换
    {
        int temp;
        temp = input[i];
        input[i] = input[largest];
        input[largest] = temp;
        heap_max(input,largest,n); //递归调用,保证子树也是最大堆
    }
    
}

解法二:利用STL的优先级队列

//堆排序解法二:利用STL的优先级队列
void heap_sort2(vector<int> &input)
{
    //priority_queue< int, vector<int>, greater<int> > a;  // 小顶堆
    //priority_queue< int, vector<int>, less<int> > q;     // 大顶堆
    priority_queue<int> a;  //默认是大顶堆
    for(int i=0;i<input.size();i++)
    {
        a.push(input[i]);//优先级队列在push的时候就已经自动排序了,最大值在第一个,后面的没有排序
    }
    for(int j=0;j<input.size();j++)
    {
        input[input.size()-1-j] = a.top(); //把最大值给到最后一个
        //input[j] = a.top();//小顶堆是直接对应赋值
        a.pop();
    }

}

解法三:利用#include <algorithm 里的把迭代器指定的range当堆 以及make_heap、push_heap、pop_heap、sort_heap

void heap_sort3(vector<int> &input)
{
    //make_heap(input.begin(),input.end(), less<int>());//创建大顶推 此时向量第一个元素为最大值
    //make_heap(input.begin(),input.end(), greater<int>());//创建小顶推 此时向量第一个元素为最小值
    for(int i=0;i<input.size()-1;i++)
    {
        make_heap(input.begin()+i,input.end(), greater<int>());
        
    }

}

参考文献:

1、C++中两种实现堆的方式:make_heap和priority_queue

2、c++优先队列(priority_queue)用法详解

3、剑指offer39题解法

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值