算法初探——分治法

分治法的算法设计

划分、把整个问题划分成若干子问题
求解
合并

分析过程

建立递归方程,求解
下面用一个具体的事例说明O(∩_∩)O~

元素选取的线性时间算法

Input i个不同的元素构成的集合X,整数k
Output x属于X 使得X中恰有k-1个元素小于x

第一步 分组,每组5个数,最后一组可能小于5个数

第二步 将每组数分别选用任何一种排序算法排序,选出每组中的中位数。此处无需考虑排序的复杂度,对于5个数的操作次数为10*(n/5的向上取整) T(n)=Θ(1)

第三步 将得到的中位数作为新的数组再次调用排序求中位数,记为x

第四步 用x对数据完成划分,比较所有数和x的大小,分别存在两个数组中,并记录第一个数组的个数k(x存放在第二个数组中)

第五步 划分好后
如果k=i-1 则返回x 程序结束
如果k>i-1 则在第一个数组中递归选取第i大的数
如果k〈i-1 则在第二个数组中递归选取第i-k大的数

考虑以上算法的时间复杂度
第一、二步 T(n)=Θ(n)
第三部的 T(n)=Θ(n/5向下取整)
第四步 T(n)=Ο(n)

第五步的时间复杂度较为复杂 每次递归至少会减少3/10n
T(n)= T(7n/10+6)

因此
T(n)=Θ(n/5向下取整)+T(7n/10+6)+Θ(n)=Ο(n)因此该算法是线性的

附上c代码,初学者自己敲的写的不好╮(╯﹏╰)╭

c源码

#include <stdio.h>
#include <math.h>
#include <stdlib.h>
#define M 100
void Bubblesort(int *array,double length)   //对传过来的元素的前length位排序
{
    int i,j;
    int temp;
    for(i=0;i<length-1;i++)
       {
           for(j=i+1;j<length;j++)
              {
              if (array[j]<array[i])
                 {
                  temp=array[i];
                  array[i]=array[j];
                  array[j]=temp;
                 }
              }
       }    
}

void Linetime(int *array,double length,int k)
{  
    int i,j,h,l,a=0,b=0,bin[M],min[M],max[M],transit[5],*s,*f,*r;
    double q,c,d;
    r=transit;     
    q=floor(length/5);    //将数据分组,每组5个,最后一组可不够5个
    for (i=0;i<q;i++)    //将5个数据暂时放到transit中 
            {
              for (h=0;h<5;h++)
              {
                transit[h]=array[i*5+h];
              }
             Bubblesort(r,5);     //对transit排序
             bin[i]=transit[2];   //对transit取中位数

            } 
        j=(int)(length-floor(length/5)*5);  //计算不足5个的最后一组元素个数 


        if (j !=0)       //重复上述步骤
        {
            for (h=0;h<j;h++)
              {
                transit[h]=array[i*5+h];
              }
        Bubblesort(r,j);

        j=(int)(ceil(j*1.0/2)-1);

        bin[i]=array[i*5+j];
        }
        f=bin;

        Bubblesort(f,i*1.0);       //对选出的元素数组再次排序

        l=(int)(ceil(i*1.0/2)-1);    //确定中位数

        for (i = 0; i < length; i++)    //扫描判断
        {

            if (array[i] < bin[l])      //小于放到数组min中
            {
                min[a] = array[i];
                a++;
            }
            else
            {
                max[b] = array[i];      //大于放到数组max中
                b++;
            }

          }
           c=(double)(a);
           d=(double)(b);
           if (a == k - 1)        //判断是否为第k大的数
           {
               printf("Haved found this number\n");
               printf("The number you chosed is:\n%d\n", bin[l]);
           }
         else if  (a>k-1)        //不满足,递归求解
            { 
              s=min;               
             Linetime(s,c,k);
            }
         else
            { 
              s=max;
              k=(int)(k-c);
             Linetime(s,d,k);
           }


}


int main()
{
    int a[M];
    int   i = 0,k=0; 
    int   x,j,*p;
    int   ch;
    double z; 
        p=a;
        printf("Please input the number separated by ','or' ',and end with return character:\n");
    while ((ch = fgetc(stdin)) != '\n')  //从键盘输入需要的到的元素
    {
        if (ch == ' ' || ch == ',')
            continue;
        ungetc(ch, stdin);
        scanf_s("%d",&a[i]);    //将元素存到数组a中
        i++;
    } 
    z=(double)(i);    

       printf("The number of the array is %d ,and array is:\n",i);
        for(j=0;j<i;j++)

            {
               printf("%d ",a[j]);
            } 
        printf("\n");
    printf("Please input the number and the number k must lose than i:\n");
loop:   scanf_s("%d", &k);     //选取第k大的元素
        if (k>i)
          {
               printf("error! Please input again:\n");       
               goto loop;
         }
        Linetime(p,z,k);        //调用线性时间算法选取元素

        system("pause");
        return 0;
}










你可能感兴趣的:(算法)