堆C++(堆排序+topK问题)

今天复习一下堆的知识。
先手写复现一边堆排序,C++代码如下。
代码写的是小顶堆。

void heap_build(vector &arr,int i,int size){
    int l=2*i+1;
    int r=l+1;
    int flag=i;
    if(larr[flag]){
        flag=l;
    }
    if(rarr[flag]){
        flag=r;
    }
    if(flag!=i){
        swap(arr[flag],arr[i]);
        heap_build(arr, flag, size);
    }
}

void heap_sort(vector &arr,int size){
    for(int i=size/2-1;i>=0;--i){
        heap_build(arr, i, size);
    }
    
    for(int j=size-1;j>=0;--j){
        swap(arr[0],arr[j]);
        heap_build(arr, 0, j);
    }
     
}

复杂度为O(nlogn)

堆排序是解决topK问题的好方法。

leetcode215

在未排序的数组中找到第 k 个最大的元素。
请注意,你需要找的是数组排序后的第 k 个最大的元素,而不是第 k 个不同的元素。

方法1: 直接用priority_queue优先队列实现

//C++ 优先队列默认大顶堆,若用小顶堆则可变为负数
class Solution {
public:
    int findKthLargest(vector& nums, int k) {
        priority_queue q;
        for(int i=0;i

方法2: 自己定义堆实现
利用之前的构建堆方法,构造一个k大小的小顶堆,再把接下来每个元素与堆顶进行比较。若大于堆顶,就弹出堆顶,插入当前元素,再次排序。

//
//  main.cpp
//  t
//  heap implementation
//
//  Created by Fang Hantao on 2020/12/30.
//

#include
#include
#include
using namespace std;

void heap_build(vector &arr,int i,int size){
    int l=2*i+1;
    int r=l+1;
    int flag=i;
    if(larr[flag]){
        flag=l;
    }
    if(rarr[flag]){
        flag=r;
    }
    if(flag!=i){
        swap(arr[flag],arr[i]);
        heap_build(arr, flag, size);
    }
}

void heap_sort(vector &arr,int size){
    for(int i=size/2-1;i>=0;--i){
        heap_build(arr, i, size);
    }
    
    for(int j=size-1;j>=0;--j){
        swap(arr[0],arr[j]);
        heap_build(arr, 0, j);
    }
    
}

// 返回第二个大的数 k=2
int main(int argc, const char * argv[]) {
    vectorarr={3,2,1,5,6,4,9,7};
    int k=2;
    heap_sort(arr,k);
    vector brr=arr;
    for(int i=3;iarr[0]){
            arr[0]=a;
            heap_sort(arr,k);
        }
    }
    cout<

leetcode347

给定一个非空的整数数组,返回其中出现频率前 k 高的元素。

本题思路很清晰,唯一问题就是堆排序的数据应该是出现次数。
参考了题解,将堆的数据类型设置为pair 左为值,右为出现次数,再重新设置排序规则。代码如下:

class Solution {
public:
    static bool cmp(pair& m, pair& n) {
        return m.second > n.second;
    }

    vector topKFrequent(vector& nums, int k) {
        int n=nums.size();
        unordered_map mp;
        for(auto a : nums){
            mp[a]++;
        }
        priority_queue,vector>,decltype(&cmp)> q(cmp);

        auto it=mp.begin();
        for(it;it!=mp.end();++it){
            if(q.size()==k){
                if(it->second>q.top().second){
                    q.pop();
                    q.push(make_pair(it->first,it->second));
                }
            }
            else{
                q.push(make_pair(it->first,it->second));
            }
        }
        vector arr;
        while(!q.empty()){
            arr.push_back(q.top().first);
            q.pop();
        }
        return arr;
    }
};

其中,这段代码我觉得值得好好学习。我一开始也看不懂,后来翻了stl源码才理解。 还是知道的太少了。不能局限在int类型,思路太窄。

 priority_queue,vector>,decltype(&cmp)> q(cmp);
// 第一个参数为数据类型T,第二个为组成的序列,第三个相当于排序规则。

你可能感兴趣的:(算法,堆排序,c++,算法,数据结构)