蛮力法和分治法的性能比较.docx
《蛮力法和分治法的性能比较.docx》由会员分享,可在线阅读,更多相关《蛮力法和分治法的性能比较.docx(11页珍藏版)》请在冰豆网上搜索。
蛮力法和分治法的性能比较
蛮力法与分治法求解最近对问题
1、蛮力法
蛮力法是一种简单直接地解决问题的方法,常常直接基于问题的描述和所涉及的概念定义,来求解问题。
虽然巧妙和高效的算法很少来自于蛮力法,但它仍是一种重要的算法设计策略:
(1)适用泛围广,是能解决几乎所有问题的一般性方法;
(2)常用于一些非常基本、但又十分重要的算法(排序、查找、矩阵乘法和字符串匹配等);
(3)解决一些规模小或价值低的问题;
(4)可以做为同样问题的更高效算法的一个标准;
(5)可以通过对蛮力法的改进来得到更好的算法。
2、分治法
分治法,就是分而治之即把一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题直到问题解决。
分治法在求解问题时,效率比较高,也是一种重要的算法策略:
(1)该问题的规模缩小到一定的程度就可以容易地解决;
(2)该问题可以分解为若干个规模较小的相同问题,即该问题具有最优子结构性质;
(3)利用该问题分解出的子问题的解可以合并为该问题的解;
(4)该问题所分解出的各个子问题是相互独立的,即子问题之间不包含公共的子子问题。
算法的基本思想及复杂度分析
1.蛮力法
(1)基本思想
蛮力法求解最近对问题的过程是:
分别计算每一对点之间的距离,然后通过排序找出距离最小的一对,为了避免对同一对点计算两次距离,只考虑i(2)复杂度分析
算法的基本操作是计算两个点的欧几里得距离。
在求欧几里得距离时,我们要避免求平方根操作,因为求平方根时要浪费时间,而在求解此问题时,求解平方根并没什么更大的意义。
如果被开方的数越小,则它的平方根也越小。
因此,算法的基本操作就是求平方即可,其执行次数为:
T(n)==2=n(n-1)=O(n)
2.分治法
(1)基本思想
用分治法解决最近对问题,就是将集合S分成两个子集S1和S2,每个子集中有n/2个点。
然后在每个子集中递归的求其最接近的点对,在求出每个子集的最接近点对后,关键问题是如何实现分治法中的合并步骤,如果组成S的最接近点对的2个点都在S1中或都在S2中,则问题很容易解决。
但是,如果这2个点分别在S1和S2中,则对于S1中任一点p,S2中最多只有n/2个点与它构成最接近点对的候选者,仍需计算才能得到准确结果。
(2)复杂度分析
应用分治法求解含有n个点得最近对问题,其时间复杂性可由下面的递推式表示:
T(n)=2T(n/2)+f(n)
合并子问题的解的时间f(n)=O
(1),由通用分治递推式的主定理可得:
T(n)=O(nlogn)
为提高算法效率,在算法中采用预排序技术,即在使用分治法之前,预先将S中的n个点依其y坐标排序好。
经过预排序处理后的算法所需的计算时间T(n)满足递归方程:
当n小于4时,T(n)=O
(1);当n大于等于4时,T(n)=2T(n/2)+O(n)。
由此易知,T(n)=O(nlogn)。
预排序所需的计算时间显然为O(nlogn)。
因此,整个算法所需的计算时间为O(nlogn)在点的个数比较少的时候,蛮力法所用时间比分治法少,点数比较多的情况下,分治法的优势就很明显了,所用时间明显比蛮力法少。
算法描述
(1)蛮力法在最近对问题中的算法描述
程序:
importjava.util.*;
publicclassmanlifa{
publicstaticvoidmain(String[]args)
{
Scannerin=newScanner(System.in);
System.out.println("有多少对点需要比较?
");
intn=in.nextInt();
int[]x=newint[n];
int[]y=newint[n];
System.out.println("请输入这些点,横坐标:
");
for(inti=0;i{
x[i]=in.nextInt();
}
System.out.println("请输入这些点,纵坐标:
");
for(inti=0;i{
y[i]=in.nextInt();
}
doubleminDist=Double.POSITIVE_INFINITY;
doubled;
intindexI=0;
intindexJ=0;
doublestartTime=System.currentTimeMillis();//startTime
for(inti=0;i{
for(intj=i+1;j{
d=Math.sqrt((x[i]-x[j])*(x[i]-x[j])+(y[i]-y[j])*(y[i]-y[j]));
if(d{
minDist=d;
indexI=i;
indexJ=j;
}
}
}
doubleendTime=System.currentTimeMillis();//endTime
System.out.println("比较的点为:
("+x[indexI]+","+y[indexI]+")and("+x[indexJ]+","+y[indexJ]+")");
System.out.println("最近距离为:
"+minDist);
System.out.println("基本语句用时"+(endTime-startTime)+"milliseconds!
");
}
}
运行结果:
(2)分治法在最近对问题中的算法描述
importjava.util.*;
publicclassfenzhifa
{
publicstaticvoidmain(String[]args)
{
Scannerin=newScanner(System.in);
System.out.println("有多少对点需要比较?
");
intn=in.nextInt();
System.out.println("请输入这些点,x坐标和y坐标:
");
Point[]S=newPoint[n];
doublestartTime=System.currentTimeMillis();
for(inti=0;i{
intx=in.nextInt();
inty=in.nextInt();
S[i]=newPoint(x,y);
System.out.println("("+S[i].getX()+","+S[i].getY()+")");
}
/**
*求出这点的x坐标的中位数mid
*/
intminX=(int)Double.POSITIVE_INFINITY;
intmaxX=(int)Double.NEGATIVE_INFINITY;
for(inti=0;i{
if(S[i].getX()minX=S[i].getX();
if(S[i].getX()>maxX)
maxX=S[i].getX();
}
intmid=(minX+maxX)/2;
ArrayListpoint1=newArrayList();
ArrayListpoint2=newArrayList();
for(inti=0;i{
if(S[i].getX()<=mid)
point1.add(S[i]);
else
point2.add(S[i]);
}
Point[]S1=newPoint[point1.size()];
Point[]S2=newPoint[point2.size()];
point1.toArray(S1);
point2.toArray(S2);
sortX(S1);
sortX(S2);
doubleminDist1=Double.POSITIVE_INFINITY;
intindexI1=0;
intindexJ1=0;
for(inti=0;i{
for(intj=i+1;j{
doubled=Math.sqrt(Math.pow((S1[i].getX()-S1[j].getX()),2)+Math.pow((S1[i].getY()-S1[j].getY()),2));
if(d{
minDist1=d;
indexI1=i;
indexJ1=j;
}
}
}
doubleminDist2=Double.POSITIVE_INFINITY;
intindexI2=0;
intindexJ2=0;
for(inti=0;i{
for(intj=i+1;j{
doubled=Math.sqrt(Math.pow((S2[i].getX()-S2[j].getX()),2)+Math.pow((S2[i].getY()-S2[j].getY()),2));
if(d{
minDist2=d;
indexI2=i;
indexJ2=j;
}
}
}
doubled1=Math.min(minDist1,minDist2);
ArrayListpp1=newArrayList();
ArrayListpp2=newArrayList();
for(inti=0;i{
if((mid-S1[i].getX())pp1.add(S1[i]);
}
for(inti=0;i{
if((S2[i].getX()-mid)pp2.add(S2[i]);
}
Point[]P1=newPoint[pp1.size()];
Point[]P2=newPoint[pp2.size()];
pp1.toArray(P1);
pp2.toArray(P2);
/**
*将P1和P2中的点按Y坐标升序排列
*/
sortY(P1);
sortY(P2);
doubled2=Double.POSITIVE_INFINITY;
for(inti=0;i{
for(intj=0;j{
if(Math.abs(P1[i].getY()-P2[j].getY()){
doubletemp=Math.sqrt(Math.pow((P1[i].getX()-P2[j].getX()),2)+Math.pow((P1[i].getX()-P2[j].getX()),2));
if(tempd2=temp;
}
}
}
doubleendTime=System.currentTimeMillis();//endtime
doubleminDist=Math.min(d1,d2);
Sys