c++ 快排思想查找第k小数……注意是小

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了c++ 快排思想查找第k小数……注意是小相关的知识,希望对你有一定的参考价值。

RT 
给定一个大小为n的数组s和一个整数K,请找出数组中的第K小元素。
  这是一个补充程序的试题,你需要完成一个函数:
  int findKth(int *s, int n, int K)
  表示在s指向的数组中找到第K小的元素(如果K=1,表示找最小元素),你需要返回该元素的值。

可以通过改写快速排序算法解决
一趟排序划分出基准位置pivot
1. pivot == k - 1,则pivot 位置数据就是
2. pivot > k - 1,则在左半继续寻找
3. pivot < k - 1,则在右半继续寻找
以下是程序:
int select(int s[ ], int left, int right, int k)
// 在s[ left .. right ]中选择第k 小的元素
if (left >= right)
return s[left];
int i = left; // 从左至右的标志
int j = right + 1; // 从右到左的标志
int pivot = s[left]; // 将最左面的元素作为分界数据
while (true)

do
// 在左侧寻找>= pivot 的元素
i = i + 1;
while (s[i] < pivot);
do
// 在右侧寻找<= pivot 的元素
j = j - 1;
while (s[j] > pivot);
if (i >= j) // 未发现交换对象
break;
int temp = s[i];
s[i] = s[j];
s[j] = temp;

if (j - left + 1 == k)
return pivot;
s[left] = s[j]; // 设置pivot
s[j] = pivot;
if (j - left + 1 < k) // 对一个段递归
return select(s, j + 1, right, k - j - 1 + left);
else
return select(s, left, j - 1, k);


int findKth(int *s, int n, int K)
// 返回 s[0 .. n - 1]中第K 小的元素
if (K < 1 || K > n)
throw "error";
return select(s, 0, n - 1, K);
参考技术A 程序已经完成了,你看看是不是你想要的结果

#include<stdio.h>
int findKth(int *s, int n, int k)

int number,i,j,tmp=0,min=s[0];
for(i=0;i<k;i++)

min=s[i];
for(j=i;j<n;j++)

if(s[j]<min)

min=s[j];
tmp=j;


number=s[tmp];
s[tmp]=s[i];
s[i]=number;

return min;

void main()

int s[]=1,4,2,8,6,7,15,9,n=sizeof(s)/sizeof(int),k=6;
printf("第 %d 小的元素是:%d\n",k,findKth(s,n,k));
参考技术B 利用快排的思想,利用函数Partition()分段。①若pivot左边的数个数小于K,则j--; //从右向左扫描, 查找第1个关键字小于pivot的记录R[j] if(i<j

vijos1788 第k大

  可以用类似快排的快速查找算法,主要是一个分治的思想,时间复杂度为O(n)。

  快排用一个中间值把序列分为两个部分,设左边部分为[l,j],右边部分为[i,r]。

  (1)如果j<k,那么第k大必然是在[i,r]中,所以[l,j]的部分就不需要继续排序,递归查找[i,r]区间即可。

  (2)如果k<i,那么第k大必然是在[l,j]中,所以[i,r]的部分就不需要继续排序,于是我们就递归查找[l,j]。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
inline int read(){
    char c; while(c=getchar(),!isdigit(c)); int x=c-0;
    while(c=getchar(),isdigit(c)) x=x*10+c-0; return x;
}
int a[100001];
int find(int l,int r,int x){
    int i=l,j=r,mid=a[l+r>>1];
    while(i<=j){
        while(i<r && a[i]>mid) i++;
        while(j>l && a[j]<mid) j--;
        if(i<=j) swap(a[i++],a[j--]);
    }
    if(j<x && x<i) return mid;
    if(x<=j) return find(l,j,x);
    if(x>=i) return find(i,r,x);
}
int main(){
    int n=read(),k=read();
    for(int i=1;i<=n;i+=1) a[i]=read();
    printf("%d",find(1,n,k));
    return 0;
}

 

以上是关于c++ 快排思想查找第k小数……注意是小的主要内容,如果未能解决你的问题,请参考以下文章

如何用快排思想在O(n)内查找第K大元素?

寻找第K大 —— 快排思想 / 堆排思想

寻找第K大 —— 快排思想 / 堆排思想

寻找第K大 —— 快排思想 / 堆排思想

寻找第K大 —— 快排思想 / 堆排思想

vijos1788 第k大