分治与递归-线性时间选择

Posted kk980414

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了分治与递归-线性时间选择相关的知识,希望对你有一定的参考价值。

问题描述:给定线性序集中n个元素和一个整数k,1≤k≤n,要求找出这n个元素中第k个元素。

算法描述:

技术分享图片

算法实现:

#include<stdio.h>
#include<stdlib.h>

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=15;
    int a[15]={41,58,96,7,5,857,589,415,27,398,215,86,71,88,85};
    for(int i=0;i<n;i++)
         printf("%d ",a[i]);*/ //检查程序时用的数组
    printf("
");     
    int k;
    scanf("%d",&k);//输入k
    int answer;//order-1
    if(k>n)printf("scan error");//k>n,输入错误
    else 
    {
        answer=selectorder(k-1,a,0,n-1);//调用selectorder函数,
                                        //得到第k小元素并赋值给answer
        printf("%d
",answer);
    }
    sord(a,0,n-1);
    for(int i=0;i<n;i++)printf("%d ",a[i]);//对数组a中元素进行选择排序、输出,为了检查程序
    return 0;    
} 
void sord(int *a,int h,int t)//对数组a中(从第h个到第t个)元素进行选择排序
{
    int temp;
    int i,j;
    for(i=h;i<=t-1;i++)
      for(j=i+1;j<=t;j++)
         if(a[i]>a[j])
          {temp=a[i];a[i]=a[j];a[j]=temp;} 
}
int partition(int *a,int h,int t,int k)//根据元素k将数组a(从第h个到第t个)
                                       //划分成元素小于k的左半部分和大于k的右半部分
{
    int i=h;
    int j=t;
    int temp;
    while(i<j)
    {
        while(a[i]<k)i++;
        while(a[j]>k)j--;
        temp=a[i];a[i]=a[j];a[j]=temp;
    }
    for(int j=h;j<=t;j++)if(a[j]==k)break;
    a[j]=a[i];a[i]=k;
    return i;
} 
    
int selectorder(int x,int *a,int h,int t)
{

    if(t-h+1<75)
    {
        if(t>h)sord(a,h,t);
        return a[x];
    }//如果当前数组范围内元素个数小于75,
     //对此范围内数组元素进行选择排序并返回a[x]
    else
    { 
        int i;
        int temp;
        for(i=0;i<=(t-h-4)/5;i++)
          {
              sord(a,h+i*5,h+i*5+4);
              temp=a[h+i];
              a[h+i]=a[h+i*5+2];
              a[h+i*5+2]=temp;
          }//将n个元素划分成?n/5?个组,
           //对每个组进行选择排序,
           //将每个组的中位数调到数组前部    
        int k=selectorder(h+((t-h-4)/5)/2,a,h,h+(t-h-4)/5);
        //找出位于数组前部中每个组的中位数中的中位数            
        i=partition(a,h,t,k);
        //根据k对数组a(从第h个到第t个)进行划分,
        //左边元素值比k小,右边元素比k大, 
        //返回i为k在数组中的位置        
        if(i==x)return(a[i]);//找到数组中第x+1小元素
        else
        {
            int j=i+1;            
            if(x<j)return selectorder(x,a,h,i-1);//从k的左半部分数组元素中找第x+1小元素
            else return selectorder(x,a,j,t);//从k的右半部分数组元素中找第x+1小元素
        }
    }
}

 

以上是关于分治与递归-线性时间选择的主要内容,如果未能解决你的问题,请参考以下文章

分治与递归-找k个临近中位数的数

递归与分治法

分治法线性时间选择(转)

算法设计与分析分治法--快速排序的递归和非递归实现

算法浅谈——分治算法与归并快速排序(附代码和动图演示)

ZROI 19.08.03 分治与离线