快速选择问题

来源:互联网 发布:网络直播的看法与态度 编辑:程序博客网 时间:2024/06/07 02:30

快速选择问题

快速选择问题。输入n个整数和一个正整数k(1kn),输出这些整数从小到大排序后的第k个(例如,k=1就是最小值)。n107

从题目上看,其n的的取值范围为[1,107],由之前的那张算法时间复杂度选择表,可以看出,使用O(nlog2n)及以上时间复杂度超时的可能性非常大,这时候最好的选取O(n)及以下时间复杂度的算法。

因为是选取一个序列中第k大的元素,那么无疑会想到使用分治法进行求解,如果采用像归并排序这样的分治方法,那么时间复杂度毫无疑问是O(nlog2n),这时,不妨想想和归并排序一样采用分治思想的快速排序。由于快速排序不需要合并步骤,且快速选择问题只需要递归一半,其时间复杂度为O(n)

分治三部曲
划分问题:通过标兵元素,将序列划分为左右两部分,左边的元素都小于等于标兵,右边的元素都大于等于标兵。
递归求解:假设A[p...r],划分后左部分为A[p...q]右部分为A[q+1...r],将k与划分后A[qp+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 109个数是:12排序之后:1 2 3 4 9 8 9 10 12 33 Process returned 0 (0x0)   execution time : 0.037 sPress any key to continue.
0 0