目录
引入
快排划分函数的思想
快排划分步骤如图
代码实现
例如问题需要求10万个整数中,值最大(小)的第10 个元素或者值最大(小)的前10个元素。
10万个整数如果是有序的那会很简单的就求出,但是如果是无序的,那就很困难。如果我们要将10万个数全部排序的话,那也是效率极低的。这时我们可以采用快排的划分函数的方法来解决此问题。
每次设置一个基准数,大于基准数的值放在右边,小于基准数的值放在左边,最后将基准数放在合适的位置,并且记录基准数的下标。
求值最小思想:将基准数所在的位置与topk的 k-1(因为这里的k值是数学中的k,需要-1变成下标k)比较,基准数和top k的k -1值相等了,直接返回基准数的下标,不用再继续寻找了,基准数就是要找的第k个元素,前k个元素就是基准数左边的所有元素。当基准数小于top k的k -1值 则需要在基准数的右边进行查找。当基准数大于top k的k -1值 则需要在基准数的左边进行查找。
求值最大思想:将基准数所在的位置与topk的 k比较,基准数和top k的k 值相等了,直接返回基准数的下标,不用再继续寻找了,基准数就是要找的第k个元素,前k个元素就是基准数左边的所有元素。当基准数小于top k的k 值 则需要在基准数的右边进行查找。当基准数大于top k的k 值 则需要在基准数的左边进行查找。
#include <stdio.h> #include <stdlib.h> #include <vector> #include <algorithm> #include <iostream> using namespace std; int partation(vector<int> &vec, int i, int j) { int val = vec[i]; int l = i; int r = j; while (l < r) { while (l < r && vec[r] >= val) { r--; } if (l < r) { vec[l++] = vec[r]; } while (l < r && vec[l] <= val) { l++; } if (l < r) { vec[r--] = vec[l]; } } vec[l] = val; //放置基准数 return l; //返回基准数下标 } int min_select_topk(vector<int> &vec, int i, int j, int k) { int ret = partation(vec, i, j); //表示基准数的位置 if (ret == k - 1) //基准数和top k的k -1值相等了 (这里的k值是数学中的k,需要-1变成下标k) { return ret; } else if (ret < k - 1) //基准数小于top k的k -1值 则需要在基准数的右边进行查找 { return min_select_topk(vec, ret + 1, j, k); } else { //基准数大于top k的k -1值 则需要在基准数的左边进行查找 return min_select_topk(vec, i, ret - 1, k); } } int max_select_topk(vector<int> &vec, int i, int j,int k) { int pos = partation(vec, i, j); //表示基准数的位置 if (pos == vec.size() - k) //基准数和top k的k值相等了 { return pos; } else if (pos < vec.size() - k) //基准数小于top k的k值 则需要在基准数的右边进行查找 { return max_select_topk(vec, pos + 1, j, k); } else { //基准数大于top k的k值 则需要在基准数的左边进行查找 return max_select_topk(vec, i, pos - 1, k); } } int main() { vector <int> vec; for (int i = 0; i < 11; ++i) { vec.push_back(rand() % 100); } for (int v : vec) { cout << v << " "; } cout << endl; int pos = max_select_topk(vec, 0, vec.size() - 1, 4); cout << "第topk大:" << vec[pos] << endl; cout << "前topk大:"; for (int i = pos; i < vec.size(); ++i) { cout << vec[i] << " "; } cout << endl; int ret = min_select_topk(vec, 0, vec.size() - 1, 4); cout << "第topk小:" << vec[ret] << endl; cout << "前topk小:"; for (int i = 0; i <= ret; ++i) { cout << vec[i] << " "; } cout << endl; sort(vec.begin(), vec.end()); for (int v : vec) { cout << v << " "; } cout << endl; system("pause"); return 0; }
11个数的结果如图:
100个数的结果如图: