(p124)k分位数

来源:互联网 发布:java写界面应用 编辑:程序博客网 时间:2024/05/16 09:06

  首先,这个题意思应该是:对一个包含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];elseif (m-1<j)return Select(num,m,l,j-1);elsereturn 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;}


0 0