1、目 录1 简介 .12 算法说明 13 测试结果 .33.1 测试输入 .33.2 测试目的 .43.3 正确输出 .53.4 实际输出 .54 分析与探讨 64.1 测试结果分析 .64.2 探讨与改进 .6附录:源代码 81 简介 分治法的基本思想是将一个规模为 n 的问题分解为 k 个规模较小的子问题,这些子问题互相独立且与原问题相同。递归地解这些子问题,然后将各个子问题的解合并得到原问题的解。它的一般的算法设计模式如下:divide-and-conquer(P)if(|P|x-(Point*)b)-x;int compy(const void* a, const void* b) /实
2、现按 y 排序return (Point*)a)-y-(Point*)b)-y;备注: qsort 功 能: 使用快速排序例程进行排序用 法 : void qsort(void *base, int nelem, int width, int (*fcmp)(const void *,const void *);各参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小 4 指向函数的指针,用于确定排序的顺序属改进后算法,基数较大时效率较高。由以上的分析可知,该算法的分割步骤和合并步骤总共耗时 O(n)。因此,算法耗费的计算时间 T(n)满足递归方程:解此递归方程可得 T
3、(n)=O(nlogn)。备注:分而治之的图示如图(2-1)图(2-1)此时 S 中的点为平面上的点,它们都有 2 个坐标值 x 和 y。为了将平面上点集S 线性分割为大小大致相等的 2 个子集 S1 和 S2,我们选取一垂直线 l:x=m 来作为3分割直线。其中 m 为 S 中各点 x 坐标的中位数。由此将 S 分割为 S1=pS|pxm和 S2=pS|pxm。从而使 S1 和 S2 分别位于直线 l 的左侧和右侧,且 S=S1S2 。由于 m 是 S 中各点 x 坐标值的中位数,因此 S1 和 S2 中的点数大致相等。递归地在 S1 和 S2 上解最接近点对问题,我们分别得到 S1 和 S
4、2 中的最小距离 1 和 2。现设 =min(1,1)。若 S 的最接近点对(p,q)之间的距离d(p,q)temp)?temp:near;return near;此代码的计算时间 T(n)=2T(n/2)+O(n2)。它的解为 T(n)=O(n2),即与合并步骤的耗时同阶,显示不出比用穷举的方法好。从解递归方程的套用公式法,我们看到问题出在合并步骤耗时太多。这样做算法效率与其他算法相比效率太低,需要O(n2)的计算时间。因此我们需要改进新的方法,需要高效率设计新的算法,因此不由的想到了计算时间下界为 (nlogn)。这个下界引导我们去找问题的一个 (nlogn)算法。因此选择“分而治之”圆环
5、套圈的方法。 (其核心代码设计如下)float dist(Point a, Point b) /*求两个坐标点之间的距离*/return sqrt(float)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);float Nearest(Point* points, int n) /*求最小距离*/float temp1,temp2,temp3,temp,nearest;float left,right,d; /*当 n 小于 4 时,T(n)=O(1);*/int i,j;if(n=1) return 999999999; /*一个点情形,返回值模拟无穷*/if
6、(n=2) return dist(points0, points1); /*两个点情形*/if(n=3) /*三个点情形*/temp1=dist(points0, points1);temp2=dist(points0, points2);temp3=dist(points1, points2);return temp3x-(Point*)b)-x;int compy(const void* a, const void* b) /*实现按 y 排序*/return (Point*)a)-y-(Point*)b)-y;经过预排序处理后的算法所需的计算时间 T(n)满足递归方程:显而易见 T(n
7、)=O(nlogn),预排序所需的计算时间为 O(n1ogn)。因此,整个算法所需的计算时间为 O(nlogn)。在渐近的意义下,此算法已是最优的了附录:源代码/* 分治法解决最小套圈问题 */#include #include #include #define MAX_POINTS 100000 /*坐标点数的最大值 */#define MAX_TEST 100 /*最大测试次数*/typedef struct /*定义坐标点*/float x;float y;Point;8float dist(Point a, Point b) /*求两个坐标点之间的距离*/return sqrt(flo
8、at)(a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y);float Nearest(Point* points, int n) /*求最小距离*/float temp1,temp2,temp3,temp,nearest;float left,right,d; /*当 n 小于 4 时,T(n)=O(1);*/int i,j;if(n=1) return 999999999; /*一个点情形,返回值模拟无穷*/if(n=2) return dist(points0, points1); /*两个点情形*/if(n=3) /*三个点情形*/temp1=dist(poi
9、nts0, points1);temp2=dist(points0, points2);temp3=dist(points1, points2);return temp3x-(Point*)b)-x;9int compy(const void* a, const void* b) /*实现按 y 排序*/return (Point*)a)-y-(Point*)b)-y;void main() int i,j=0,numPoints;Point pointsMAX_POINTS;float resultMAX_TEST; /*记录结果*/for(i=0;iMAX_POINTS) printf(“
10、Error!n“); /*容错处理*/goto loop;for(i=0; inumPoints; i+) /*输入点的数量及点的坐标值*/scanf(“%f %f“, /*预排序,在使用分治法之前,预先将 S 中的 n 个点依其 y 坐标排序好。*/qsort(points, numPoints, sizeof(Point), compx);qsort(points, numPoints/2, sizeof(Point), compy);qsort(points+numPoints/2, numPoints-numPoints/2, sizeof(Point), compy);resultj
11、=Nearest(points, numPoints)/2;j+;i=0;printf(“n 最短距离分别为:n“);while(resulti!=-1) /*输出测试结果*/printf(“%.2fn“,resulti+);/* 附:* qsort 功 能: 使用快速排序例程进行排序* 用 法: void qsort(void *base, int nelem, int width,* int (*fcmp)(const void *,const void *);* 各参数:1 待排序数组首地址 2 数组中待排序元素数量 3 各元素的占用空间大小* 4 指向函数的指针,用于确定排序的顺序10* 属改进后算法,基数较大时效率较高 */参考文献:1张益新,沈雁.算法引论M.长沙:国防科技大学出版社,1995.2苏德富,钟诚.计算机算法设计与分析M.北京:电子工业出版社,2001.3王晓东.计算机算法设计与分析M.北京:电子工业出版社,200111摘要