快速选择问题
2016-05-29 20:25
190 查看
快速选择问题
快速选择问题。输入n个整数和一个正整数k(1≤k≤n),输出这些整数从小到大排序后的第k个(例如,k=1就是最小值)。n≤107。从题目上看,其n的的取值范围为[1,107],由之前的那张算法时间复杂度选择表,可以看出,使用O(nlog2n)及以上时间复杂度超时的可能性非常大,这时候最好的选取O(n)及以下时间复杂度的算法。
因为是选取一个序列中第k大的元素,那么无疑会想到使用分治法进行求解,如果采用像归并排序这样的分治方法,那么时间复杂度毫无疑问是O(nlog2n),这时,不妨想想和归并排序一样采用分治思想的快速排序。由于快速排序不需要合并步骤,且快速选择问题只需要递归一半,其时间复杂度为O(n)。
分治三部曲
划分问题:通过标兵元素,将序列划分为左右两部分,左边的元素都小于等于标兵,右边的元素都大于等于标兵。
递归求解:假设A[p...r],划分后左部分为A[p...q]右部分为A[q+1...r],将k与划分后A[q−p+1]进行比较,小于则只在左部分递归,大于则只在右部分递归。
合并问题:无合并过程。
实现主程序
#include <iostream> #include <algorithm> #include <ctime> #include <fstream> using namespace std; // 快速排序算法 int qSort(int *a, int lef, int righ, int k) { // 递归边界 if(lef > righ) { return 0; } // 取标兵值 int centerV = a[lef + (righ - lef) / 2]; // 大于标兵值的元素放在标兵值右边 // 小于标兵值的元素放在标兵值左边 int i = lef; int j = righ; while(i <= j) { // 从左往右扫描到大于标兵值的元素 for(; i <= j; i++) { if(a[i] >= centerV) { break; } } // 从右往左扫描到小于标兵值的元素 for(; j >= i; j--) { if(a[j] <= centerV) { break; } } // 退出条件 if(i > j) { break; } // 交换 swap(a[i], a[j]); i++; j--; } if(k - 1 <= i) { // 递归求解左半 return qSort(a, lef, j, k); } else if(k - 1 > i + 1) { // 递归求解右半 return qSort(a, i, righ, k); } else{ return a[k - 1]; } } int quickSort(int *a, int n, int k) { return qSort(a, 0, n - 1, k); } int main() { // 测试数据(小量) // int a[] = {4432, 3, -3, 5, 5, 3, 5435, -11, 3423, -1, -4421, 34432}; // int a[] = {1,2,3,4,9,8,7,8,9,10}; int a[] = {1,2,3,4,9,33,12,8,9,10}; int n = 10; int k = 9; cout << "排序之前:"; for(int i = 0; i < n; i++) { cout << a[i] << " "; } cout << endl; cout << "第" << k << "个数是:" << quickSort(a, n, k) << endl; cout << "排序之后:"; for(int i = 0; i < n; i++) { cout << a[i] << " "; } cout << endl; return 0; }
输出数据
排序之前:1 2 3 4 9 33 12 8 9 10 第9个数是:12 排序之后:1 2 3 4 9 8 9 10 12 33 Process returned 0 (0x0) execution time : 0.037 s Press any key to continue.
相关文章推荐
- 快速排序
- 书评:《算法之美( Algorithms to Live By )》
- 动易2006序列号破解算法公布
- Ruby实现的矩阵连乘算法
- C#插入法排序算法实例分析
- 超大数据量存储常用数据库分表分库算法总结
- C#数据结构与算法揭秘二
- C#冒泡法排序算法实例分析
- C#快速排序算法实例分析
- 算法练习之从String.indexOf的模拟实现开始
- C#算法之关于大牛生小牛的问题
- C#实现的算24点游戏算法实例分析
- c语言实现的带通配符匹配算法
- 浅析STL中的常用算法
- 算法之排列算法与组合算法详解
- C++实现一维向量旋转算法
- Ruby实现的合并排序算法
- C#折半插入排序算法实现方法
- 基于C++实现的各种内部排序算法汇总
- C++线性时间的排序算法分析