分治法的算法设计
划分、把整个问题划分成若干子问题
求解
合并
分析过程
建立递归方程,求解
下面用一个具体的事例说明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;
}