c++ topk问题

 

https://blog.csdn.net/SmartDemo/article/details/107572238

https://blog.csdn.net/wuqingshan2010/article/details/108508676

# scores数组为std::vector<float>
		// topK
		// 排序
		std::vector<size_t> idx(scores.size());
	std::iota(idx.begin(), idx.end(), 0);
	std::sort(idx.begin(), idx.end(),
		[&scores](size_t index_1, size_t index_2) { return scores[index_1] > scores[index_2]; });
	// 获取K值
	int k_num = std::min<int>(scores.size(), K);
	std::vector<float> scores_K;
	int idx_j = 0;
	for (int j = 0; j < k_num; ++j) {
		idx_j = idx[j];
		scores_K.push_back(scores[idx_j]);
	}

https://blog.csdn.net/doctor_xiong/article/details/81083942

例如:arr[] = {9,1,6,2,3,8,3,4,7,0}最大的四个元素是6,7,8,9

思路:使用小堆,先将数组中的K个元素插入到堆中,然后再从第K个开始遍历数组,如果数组中的元素大于,堆顶元素,就将对顶元素pop,然后再将数组中的元素push进堆里面去

实现代码:

#include<iostream>
using namespace std;
#include<queue>
class compare{
    public:
    bool operator()(int a,int b){
        return a > b;
    }
};

int* FindTopK(int* arr,int n,int* ret,int m){
    compare com;
    priority_queue<int,vector<int>,greater<int> > q(arr,arr+m);
    int i = m;
    for(;i<n;i++){
        if(arr[i] > q.top()){
            q.pop();
            q.push(arr[i]);
        }
    }
    int j = 0;
    while(!q.empty()){
        ret[j++] = q.top();
        q.pop();
    }
}

int main(){
    int arr[] = {9,4,5,2,5,1,7,3,1,8};
    int ret[5];
    FindTopK(arr,10,ret,5);
    for(int i = 0;i<5;i++)
        cout<<ret[i]<<" ";
    return 0;
}

参考1:

https://blog.csdn.net/qq_37891889/article/details/88621591

参考2:

https://blog.csdn.net/weixin_43860854/article/details/108616568

参考3:

https://blog.csdn.net/propro1314/article/details/43091387

参考:https://blog.csdn.net/Hairy_Monsters/article/details/79776744 

/*第一种情况——二叉堆C++代码实现*/
/*
*代码采用STL中的最小优先队列实现,由于STL中自带最小优先队列,其底层就是二叉堆实现,
*所以就不再手写二叉堆了。最小优先队列顶层元素总是队列中最小的元素,也就是二叉堆堆顶。
*/
 
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
 
/*由于STL自带优先队列是默认最大优先的,所以自己写了一个比较函数,将其改为最小优先*/
struct cmp1 {
	bool operator ()(int &a, int &b) {
		return a>b;											//最小值优先
	}
};
 
int main() {
	//这里用来测试,输入格式:先输入需要求的最大K个数中的K值,再依次输入数据流
	int K = 0;
	cin >> K;
	int tmp = 0;
	int i = 0;
	priority_queue<int,vector<int>,cmp1> minHeap;			//建立最小优先队列
	while (cin >> tmp) {									//循环输入数据流
		if (i < K) {										//先建立一个K个大小的优先队列,也就是K大小的二叉堆
			minHeap.push(tmp);
		}
		else {												//算法实现
			if (tmp <= minHeap.top())
				continue;
			else if (tmp > minHeap.top()) {
				minHeap.pop();
				minHeap.push(tmp);
			}
		}
		i++;
	}
	while (!minHeap.empty()) {								//输出最大的K个数
		cout << minHeap.top() << endl;
		minHeap.pop();
	}
	return 0;
}
 
/*第二种情况——Quick Select C++代码实现*/

/*Quick Select*/
#include <iostream>
#include <vector>
 
using namespace std;
 
int Partition(vector<int> &vec, int p, int r) {				//实现快排中Partition函数,输入原数组引用,以及需要运行的左右下标
	if (p >= r)												//非法输入,Partition具体思想参照快排详解
		return r;
	int tmp = vec[r];
	int i = p;
	int j = p;
	while (i < r) {
		if (vec[i] <= tmp) {
			int temp = vec[i];
			vec[i] = vec[j];
			vec[j] = temp;
			i++;
			j++;
		}
		else if (vec[i] > tmp) {
			i++;
		}
	}
	vec[r] = vec[j];
	vec[j] = tmp;
	return j;
}
 
int main() {
	int K = 0;										//测试部分,输入需要求的K值大小,然后再依次输入数组元素
	cin >> K;
	int tmp = 0;
	vector<int> vec;
	while (cin >> tmp)
		vec.push_back(tmp);
	int size = vec.size();
        if (size == 0 || k>size) return vector<int>();
        if (size== k) return input;
        int p = 0;
	int r = vec.size() - 1;
	int index = Partition(vec, p, r);
	while (index != size - K) {						//当Partition返回值及右边部分不是K大小时,继续循环
		int sizeOfRight = size - index - 1;			//记录index右边数组长度大小
		if (K <= sizeOfRight) {
			index = Partition(vec, index + 1, r);
		}
		else if (K == sizeOfRight + 1)				//这一步好像有点多余,while循环保证了这点,但为了对应博客文字描述就加上了
			continue;
		else if (K > sizeOfRight + 1) {
			index = Partition(vec, p, index - 1);
		}
	}
	for (int i = index; i < size; i++) {			//测试部分,输出需要求的K个数
		cout << vec[i] << endl;
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章