您的位置:首页 > 其它

(p124)k分位数

2016-02-16 21:28 274 查看
首先,这个题意思应该是:对一个包含n个元素的集合来说,k分位数是指能把有序集合分成k个等大小集合的k-1个顺序统计量,给出一个能找出某一集合的k分位数的O(nlgk)算法——书上多印了一个“第”字,搞得莫名其妙-_-;

好吧,既然清楚了,我们来分析以下复杂度,lgk——这说明很有可能要用到分治,再根据递归树模型,我们就可以看出来,大概有这样一个函数:find(int *num,int k,int l,int r,int *result),它的功能是找到第(l+r)/2+1个分隔点对应的顺序统计量,存到result数组里面,然后递归地对左边和右边的区间进行操作。怎么找那个顺序统计量?这一章提到的两种算法都可以,而且这两种算法都顺带将数组分为了小于分割数的一部分和大于分割数的一部分,这保证了这道题分治算法的正确性。

/*
* source.c
*
*  Created on: Feb 16, 2016
*      Author: wing
*/
#include<stdio.h>
#include<stdlib.h>
int Select(int *num,int m,int l,int r)
{
int i,j=l-1,tmp;
if (l==r)
return num[l];
for (i=l;i<=r-1;i++)
if (num[i]<num[r])
{
j++;
tmp=num[j];
num[j]=num[i];
num[i]=tmp;
}
j++;
tmp=num[j];
num[j]=num[r];
num[r]=tmp;
if (m-1==j)
return num[j];
else
if (m-1<j)
return Select(num,m,l,j-1);
else
return Select(num,m,j+1,r);
}
int find(int *num,int k,int l,int r,int *result)/*注意哦,这里的k是每个小区间有k个元素^-^*/
{
result[(l+r)/2]=Select(num,((l+r)/2+1)*k,l*k,(r+2)*k-1);
if (l==r)
return 0;
else
{
find(num,k,l,(l+r)/2,result);
find(num,k,(l+r)/2+1,r,result);
return 0;
}
}
int main(void)
{
int *num,n,k,i,*result;
scanf("%d",&n);
scanf("%d",&k);
num=(int *)malloc(sizeof(int)*n);
for (i=0;i<n;i++)
scanf("%d",&num[i]);
result=(int *)malloc(sizeof(int)*k);
find(num,n/k,0,k-2,result);
for (i=0;i<=n/k-2;i++)
printf("%d ",result[i]);
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: