算法初探——分治法

来源:互联网 发布:mac屏幕截图保存位置 编辑:程序博客网 时间:2024/06/06 01:00

分治法的算法设计

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

分析过程

建立递归方程,求解
下面用一个具体的事例说明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 100void 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;}
0 0