快速排序求第K个小的数

问题:快速排序求第k小的数,思想非常简单,就是如果要查找的k比当前下标i小,则只递归左部分,大或相等则递归右部分。当然由于数组下标从0开始,所以应该是k-1(比如第一大的数数组下标为0)。原理就是快速排序是以一个元素为分隔的,如果求第k大的元素,也就是求第n-k+1小的元素。
1、阐述原理
图片说明
快速排序的思想:将数组中某一个元素m作为划分依据(我们假设为第一个元素,即m = arr[0]),遍历一遍数组,使得数组的格局变成这样的三个部分:
(1)m前面的元素
(2)m
(3)m后面的元素。
其中m前面的元素小于m,m后面的元素大于m,这样找第k小的数正好可以借鉴这个思想,即:
①若m前面的元素个数大于k,则第k小的数一定在m前面的元素中,这时我们只需要继续在m前面的元素中搜索第k小的数;
②若m前面的元素个数小于k,则第k小的数一定在m后面的元素中,这是我们只需要继续在m后面的元素中搜索第k-s小的数,其中s是m前面的元素个数。
2、代码展示

#include<stdio.h>
void main(){
         int a[]={2,4,3,5,6,7,9,8,10,1};
         int k=6;
        printf("the %d least number is %d\n", k, qucikSelect(a, 0, sizeof(a)/sizeof(int)-1,k));
}
int qucikSelect(int a[], int s, int t, int k){
     int tmp=a[s];        //s是最开始的位置,作为start
     int i = s;
     int j = t;           //作为end
     if (s < t){
          while(i !=j){
                  while(j > i  && a[j]>tmp)
                         j--;         //如果满足j>i,并且a[j]>temp,则将end前移一个
                       a[i]=a[j];     //如果不满足,则交换元素位置
                   while(j > i && a[i] < tmp)
                       i++;             //如果满足j>i,并且a[i]<temp,则将start后移一个
                        a[j]=a[i];       //如果不满足,则交换元素位置
     }
     a[i]=tmp;        //将基数赋temp赋给a[i]
     if(i == k-1) return a[i];  //如果第i个数刚好是第k个数,则返回a[i]
     else if(i > k-1){ return qucikSelect(a, s, i-1, k);}//如果temp前面的数大于K,则在左边进行递归
     else if(i < k-1){return qucikSelect(a, i+1,t, k);}//如果temp前面的数小于K,则在右边进行递归
     }
     else{
            if(s  == t && s == k-1)   //如果s和t指针指到同一个数,且刚好是第k小的数,则返回a[s]
                return a[s];
     }
}

3、测试结果
图片说明
4、快速排序复杂度分析
图片说明
图片说明

全部评论

相关推荐

点赞 收藏 评论
分享
牛客网
牛客企业服务