快速选择

快速排序及快速选择问题

1. 快速排序

  1. 采取分治,通过找到一个中枢值,使得中枢值左边的数小于等于其值,右边大于其值。
  2. 递归求解问题
  3. 当每一个数被当做一次中枢值,这个数组已经有序
//挖坑填数+分治
//函数出口为l=r时
//把数组分成中枢两侧,采取两个指针,挖坑填数
void quickSort(int a[],int left,int right){
    int l=left,r=right,key=a[l];
    if(l<r){
        while(l<r){
            while(l<r && key<a[r])
                r--;
            a[l]=a[r];
            while(l<r && key>=a[l])
                l++;
            a[r]=a[l];
        }
        a[l]=key;
        quickSort(a,left,l-1);              //左边递归,重复上面找中枢步骤
        quickSort(a,l+1,right);             //右边递归,重复上面找中枢步骤
    }
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

2. 快速选择问题

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

在快速排序的基础上,只需要找到第k个作为中枢的值,即为有序数列的第k个数的数值

int quickSort1(int a[],int left,int right,int num){
    //快速选择问题。输入n个整数和一个正整数k(1≤k≤n),输出这些整数从小到大排序后的第k个
    //函数出口为 l==r==num  和快排有差别
    int l=left,r=right,key=a[l];
    if(l<r){
        while(l<r){
            while(l<r && key<a[r])
                r--;
            a[l]=a[r];
            while(l<r && key>=a[l])
                l++;
            a[r]=a[l];
        }
        a[l]=key;
    }
        if(num==l)                                          //此时出现要找的数组下标
            return key;
        if(num<l)
            return quickSort1(a,left,l-1,num);              //递归左区间求解   必须带return,否则函数没法一级一级返回
        else
            return quickSort1(a,l+1,right,num);             //递归左区间求解   必须带return,否则函数没法一级一级返回
}

速排序和快速问题完整代码

#include <iostream>
#include <cstring>
#include <time.h>
#include <stdlib.h>
#define N 10
using namespace std;
int quickSort1(int a[],int left,int right,int num){
    //快速选择问题。输入n个整数和一个正整数k(1≤k≤n),输出这些整数从小到大排序后的第k个
    //函数出口为 l==r==num  和快排有差别
    int l=left,r=right,key=a[l];
    if(l<r){
        while(l<r){
            while(l<r && key<a[r])
                r--;
            a[l]=a[r];
            while(l<r && key>=a[l])
                l++;
            a[r]=a[l];
        }
        a[l]=key;
    }
        if(num==l)
            return key;
        if(num<l)
            return quickSort1(a,left,l-1,num);              //递归左区间求解   必须带return,否则函数没法一级一级返回
        else
            return quickSort1(a,l+1,right,num);             //递归左区间求解   必须带return,否则函数没法一级一级返回
}
void quickSort(int a[],int left,int right){
    int l=left,r=right,key=a[l];
    if(l<r){
        while(l<r){
            while(l<r && key<a[r])
                r--;
            a[l]=a[r];
            while(l<r && key>=a[l])
                l++;
            a[r]=a[l];
        }
        a[l]=key;
        quickSort(a,left,l-1);              //左边递归,重复上面找中枢步骤
        quickSort(a,l+1,right);             //右边递归,重复上面找中枢步骤
    }
}
int a[N];
int b[N];
int main(){
    unsigned seek=unsigned(time(NULL));
    srand(seek);
    cout<<"Array:"<<endl;
    for(int i=0;i<N;i++)
    {
        a[i]=rand();
        cout<<a[i]<<"\t";
    }
    cout<<endl;
    memcpy(b,a,sizeof(a));
    quickSort(a,0,N-1);
    int pos=3;                                      //要查找数的位置
    cout<<"Result:"<<endl;
    for(int i=0;i<N;i++)
        cout<<a[i]<<"\t";

  int ans=quickSort1(b,0,N-1,pos-1);        
      cout<<endl<<"部分排序:"<<endl;                    //通过打印这个数组,验证O(n)复杂度,不是全部操作,只操作一部分
    for(int i=0;i<N;i++)
       cout<<b[i]<<"\t";
    cout<<endl<<endl<<"第 "<<pos<<" 个数是:"<<ans<<endl;
    return 0;
}

 

 


输出结果:

Array: 
11973 4898 13514 6085 14958 17750 2789 2706 20714 19060 
Result: 
2706 2789 4898 6085 11973 13514 14958 17750 19060 20714 
部分排序: 
2706 2789 4898 6085 11973 17750 14958 13514 20714 19060

第 3 个数是:4898

posted @ 2018-07-11 20:25  guguchen  阅读(46)  评论(0编辑  收藏  举报