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;
}