随机化查找第k小元素:不必将所有元素按从大到小或从小到大排序即可找出第k小值
思路:随机从序列中取一值,从第一个值开始,将比起小的放在左面,比起大的放在右面。然后比较k与这个值的位置(数组下角标,我设置成从1开始的)如果k的值比这个值的下角标大,那么取这个值的右半部分(都比这个值小)然后再从其中取以随机值,进行如上操作,直到这个值的下角标与k相等为止。如果k的值比这个值的下角标小,那么取这个值的左半部分(都比这个值小)然后再从其中取以随机值,进行如上操作,直到这个值的下角标与k相等为止。
#include<stdio.h>
#include<time.h>
#include<stdlib.h>
unsigned long long a[50000000];
unsigned long long b[50000000];
void suiji(unsigned long long a[],unsigned long long m,unsigned long long r)
{
if(m<r)
{
unsigned long long temp=0,p;
p=rand()%(r-m+1)+m;
temp=a[m];
a[m]=a[p];
a[p]=temp;
unsigned long long i=m;
unsigned long long j=r;
while(i<j)
{
while(a[i]<a[j]&&i<j)
{
j--;
}
if(i<j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
i++;
}
while(a[i]<a[j]&&i<j)
{
i++;
}
if(i<j)
{
temp=a[i];
a[i]=a[j];
a[j]=temp;
j--;
}
}
if(i==j)
{
suiji(a,m,i-1);
suiji(a,i+1,r);
}
}
}
void chazhao(unsigned long long a[],int l,int r,int k)
{
int n=l,m=r,p,i,q=0,v=0;
p=rand()%(r-l+1)+l;
for(i=r;i>=l;i--)
{
if(a[i]>a[p])
{
b[m]=a[i];
m--;
}
else if(a[i]<a[p])
{
b[n]=a[i];
n++;
}
else
{
q++;
}
}
for(i=n;i<=m;i++)
{
b[i]=a[p];
n++;
}
for(i=l;i<=r;i++)
{
a[i]=b[i];
}
if((k>=(n-q))&&k<n)
{
printf("随机化查找第k个数是%d\n",a[k]);
}
else if(k<(n-q))
{
r=n-q-1;
chazhao(a,l,r,k);
}
else if(n<=k)
{
l=n;
chazhao(a,l,r,k);
}
}
int main()
{
int n,i,k;
printf("请输入数字个数n<=50000000:");
scanf("%d",&n);
printf("请输入k:");
scanf("%d",&k);
srand(time(NULL));
for(i=1;i<=n;i++){//随机生成待排数组
a[i]=rand();
}
clock_t beg,end;//起始时间和结束时间
double time;
beg=clock();
suiji(a,1,n);
printf("随机化快排查找第k个元素是%d\n",a[k]);
end=clock();
time=(double)(end- beg)/CLOCKS_PER_SEC;
printf("随机产生成数进行随机快排查找第k小元素的运行时间:%f s\n",time);
beg=clock();
chazhao(a,1,n,k);
end=clock();
time=(double)(end- beg)/CLOCKS_PER_SEC;
printf("随机产生成数进行随机化查找第k小元素的运行时间:%f s\n",time);
return 0;
}