分治與遞迴-找k個臨近中位數的數

DNE發表於2018-10-15

問題描述:給定由n個互不相同的陣列成的集合S以及正整數k≤n,試設計一個O(n)時間演算法找出S中最接近S的中位數的k個數。

演算法描述:

  1. 用線性時間選擇實現的演算法找到中位數
  2. S’=除去中位數外的S
  3. S”=|S`中的數值-中位數的值|
  4. 用線性時間選擇實現的演算法找到第k個最小的數
  5. 輸出S”中小於第k個最小的數的數對應的S中的值

演算法實現:

selectorder函式、partition函式、sord函式同線性時間選擇程式的演算法實現,故略。
int main()
{
    void sord(int a[],int h,int t);
    int selectorder(int x,int a[],int h,int t);
    int partition(int a[],int h,int t,int k);
    int n;
    scanf("%d",&n);
    int *a;
    a=(int *)malloc(sizeof(int)*n);
    for(int i=0;i<n;i++)
         a[i]=rand();
    for(int i=0;i<n;i++)
         printf("%d ",a[i]);
    //動態分配陣列a
    //隨機生成陣列a元素、輸出
    /*
    int n=7;
    int a[7]={0,-1,20,-4,-100,2000,2001};
    for(int i=0;i<n;i++)
         printf("%d ",a[i]);
     */   
    printf("
");       
    int middle;
    middle=selectorder((n-1)/2,a,0,n-1);
    printf("%d
",middle);
    //找到陣列a中的中位數並賦值給middle    
    int *b;
    b=(int *)malloc(sizeof(int)*n);   
    for(int i=0;i<n;i++)
      if(a[i]>=middle)b[i]=a[i]-middle;
      else b[i]=middle-a[i];
    //動態分配陣列b
    //陣列b中元素=|陣列a中元素-middle|  
    int *c;
    c=(int *)malloc(sizeof(int)*n);
    for(int i=0;i<n;i++)c[i]=b[i];
    //陣列c中元素=陣列b中元素 
    int k;
    scanf("%d",&k);
    //輸入k
    int last;
    last=selectorder(k-1,b,0,n-1);
    //找到陣列b中第k小元素並賦值給last        
    for(int i=0;i<n;i++)
     if(c[i]<=last)printf("%d ",a[i]);
    //遍歷陣列c,如果陣列c中元素小於last,
    //則輸出對應位置上陣列a的元素
    printf("
");
    sord(a,0,n-1);
    for(int i=0;i<n;i++)printf("%d ",a[i]);
      return 0;    
} 

 

相關文章