深圳大学算法设计实验二

这篇博客探讨了在计算平面上N个点的最短距离对时,蛮力法和分治法的实现与效率。实验表明,随着点的数量增加,分治法在时间复杂度上优于蛮力法,表现为更稳定的运行时间。在N=100000时,分治法的实测效率接近理论预期。此外,文章强调了在设计分治算法时降低合并开销的重要性,并建议在小规模数据上用蛮力法验证算法正确性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

更好的阅读体验

一.实验目的

  1. 对于平面上给定的N个点,给出所有点对的最短距离,即,输入是平面上的N个点,输出是N点中具有最短距离的两点。

  2. 要求随机生成N个点的平面坐标,应用蛮力法编程计算出所有点对的最短距离。

  3. 要求随机生成N个点的平面坐标,应用分治法编程计算出所有点对的最短距离。

  4. 分别对N=100,1000,10000,100000,统计算法运行时间,比较理论效率与实测效率的差异,同时对蛮力法和分治法的算法效率进行分析和比较。

  5. 如果能将算法执行过程利用图形界面输出,可获加分。

二、算法原理描述

1、蛮力法

1)算法描述:已知集合S中有n个点,一共可以组成 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2对点对,蛮力法就是对这 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2对点对逐对进行距离计算,通过循环求得点集中的最近点对:

2)伪代码描述

enumerate(const Point *test, int N)
	for i from 0 to N - 1
		for j from i + 1 to N
			ans = min(ans, dis(test[i], test[j]))

3)算法时间复杂度:算法一共要执行 n ( n − 1 ) / 2 n(n-1)/2 n(n1)/2次循环,因此算法复杂度为 O ( n 2 ) O(n^2) O(n2)

2、分治法

1)算法描述:已知集合S中有n个点,分治法的思想就是将S进行拆分,分为两部分求最近点对。每次选择一条垂线L,将S拆分左右两部分为SLSRL一般取点集S中所有点的中间点的x坐标来划分,这样可以保证SLSR中的点数目各为n/2

(否则以其他方式划分S,极端情况下可能会导致SLSR中点数目一个为1,一个为n-1,不利于算法效率的准确性)

将左右两部分继续分解为更小的两部分,直到不能继续分解为止,用P1,P2来表示这两个部分,此时最终要求的最近距离可能在左边即P1中或者在右边即P2中,还有可能这个点对一个点在左边,一个点在右边

找出这两部分中的最小点对距离:d1和d2,记P1和P2中最小点对距离 d = m i n ( d 1 , d 2 ) d=min(d1,d2) d=min(d1d2)

此时,P1中所有点与P2中所有点构成的点对均为最接近点对的候选者。在最坏情况下有 n / 2 n/2 n/2这样的候选者。

P1中任意一点p,它若与P2中的点q构成最接近点对的候选者,则必有 d ( p , q ) < d d(p,q)<d d(p,q)<d。满足这个条件的P2中的点一定落在一个 d × 2 d d×2d d×2d的矩形R中
在这里插入图片描述
由d的意义可知P2中任何2个S中的点的距离都不小于d,由此可以推出矩形R中最多只有6个S中的点。

将矩形R的长为 2 δ 2δ 2δ的边3等分,将它的长为 δ δ δ的边2等分,由此导出6个 ( d / 2 ) × ( 2 d / 3 ) (d/2)×(2d/3) d/2×2d/3的矩形。
在这里插入图片描述
若矩形R中有多于6个S中的点,则由抽屉原理易知至少有一个 d × 2 d d×2d d×2d的小矩形中有2个以上S中的点。设u,v是这样2个点,它们位于同一小矩形中,则这个小矩形中两点的最大距离即对角线的长度 s q r t ( ( d / 2 ) 2 + ( 2 ∗ d / 3 ) 2 ) = 5 ∗ d / 6 < d sqrt((d/2)^2 + (2*d/3)^2) = 5*d/6 < d sqrt((d/2)2+(2d/3)2)=5d/6<d
在这里插入图片描述
d ( u , v ) ≤ 5 d / 6 < d d(u,v)≤5d/6 < d d(u,v)5d/6<d。这与d的意义相矛盾。由反证法可以得出这个矩形R最多有6个点。

因此,在分治法的合并步骤中,我们最多只需要检查 6 × n / 2 = 3 n 6×n/2=3n 6×n/2=3n对候选者,而不是 n / 2 n /2 n/2个候选者。若将P1和P2中所有S的点按其y坐标排好序,则对P1中所有点p,对排好序的点列作一次扫描,就可以找出所有最接近点对的候选者,对P1中每一点最多只要检查P2中排好序的相继6个点。

由于分治算法的结构和归并排序的结构相类似,所以在合并的过程中采用归并排序的合并操作对候选点的y值进行排序,相当于一边递归一边排序,每次合并的排序开销为 O ( n ) O(n) O(n),因此算法整体的时间复杂度为 T ( n ) = 2 T ( n / 2 ) + O ( n ) T(n)= 2T(n/2) + O(n) T(n)=2T(n/2)+O(n) T ( n ) = O ( n l o g n ) T(n)= O(nlogn) T(n)=O(nlogn)

2)伪代码描述

merge(left, right)
	dist = INF;
	if(left == right) return dist;
		if(left + 1 == right) return 两点距离  
		mid = (left + right) / 2;
			dist1 = merge(left, mid), dist2 = merge(mid + 1, right);
			dist = min(dist1, dist2);
  1. 找出距离中点x坐标小于dist的点存入tmp数组
  2. 对tmp数组按y值进行归并排序的合并操作
  3. 对tmp数组中每个点遍历与它之后的6个点的距离更新最短距离

3)算法时间复杂度

在分解前按照x值进行排序,时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn),合并阶段的开销时间复杂度为 O ( n ) O(n) O(n),递推式为
在这里插入图片描述
计算得出算法整体的时间复杂度为 O ( n l o g n ) O(n log n) O(nlogn)

算法测试结果及效率分析;

1.蛮力法

输入规模处理时间理论值
100000.575150.5751500
200002.301362.3006000
300005.192655.1763500
400009.219319.2024000
5000014.846114.3787500
6000021.577921.5779000
7000029.025729.3699194
8000038.145338.3607111
9000048.488348.5502750
10000059.788559.9386111

先选取输入规模n=10000的实际时间t1作为理论时间的基准。
当n=20000时, t 2 = t 1 ∗ ( 2 / 1 ) 2 t2=t1*(2/1)2 t2=t1(2/1)2
当n=30000时, t 3 = t 1 ∗ ( 3 / 1 ) 2 t3=t1*(3/1)2 t3=t1(3/1)2
以此类推做出表格数值,得出的理论值曲线基本与实际值曲线基本贴合。

2.分治法

100规模

输入规模处理时间理论值
1007.06E-067.06E-06
2001.77E-051.62E-05
3002.68E-052.62E-05
4003.57E-053.67E-05
5004.65E-054.76E-05

在这里插入图片描述

1000规模

输入规模处理时间理论值
10007.40E-057.40E-05
20000.000170.000163
30000.0002670.000257
40000.0003460.000355
50000.0004360.000456

在这里插入图片描述

1w输入规模

输入规模处理时间理论值
100000.000898.90E-04
200000.0018550.001913958
300000.0029350.002988478
400000.0039850.004095833
500000.00510.005227604

在这里插入图片描述

10w规模

输入规模处理时间理论值
1000000.0110.011
2000000.02320.023324532
3000000.03510.036149
4000000.04940.049298128
5000000.06150.06268867
6000000.07530.076271597
7000000.08870.09001451
8000000.10120.103894384
9000000.11540.117894002
10000000.13060.132

在这里插入图片描述

注:在代码实现的过程中采用了 O 3 O_3 O3优化,故算法运行时间稍快

O(nlog(n))复杂度时间推导

t l = n 1 ∗ l o g ( 2 , n 1 ) ∗ t tl=n1*log(2,n1)*t tl=n1log2n1t, t1表示规模为n1的数据用时

t 2 = n 2 ∗ l o g ( 2 , n 2 ) ∗ t t2=n2*log(2,n2)*t t2=n2log2n2t,t2表示规模为n2的数据用时

t 2 = n 2 / n 1 ∗ ( l o g ( 2 , n 2 ) / 1 o g ( 2 , n 1 ) ) ∗ t 1 t2=n2/n1*(log(2,n2)/1og(2,n1))*t1 t2=n2/n1log2n2/1og2n1t1

实际运行时间基本符合上述推导,每次合并的点都限制在 d ∗ 2 d d*2d d2d的矩形之中,合并的开销稳定在 O ( n ) O(n) O(n),时间曲线较为稳定

误差分析:规模较小时,分治算法运行速度较快,而实现算法的代码采用的是time.h头文件的clock()函数进行时间测量,会导致精度的丢失,所以在较小规模的测试中误差体现比较明显,只能将测试次数提高以降低误差,测试规模增大,算法运行时间明显趋于稳定

四.对求解这个问题的经验总结

  1. 在设计分治算法的过程中要尽可能地降低合并过程的开销,如果在以上设计的分治算法中对y值的排序直接采用快速排序进行排序的话,那么实际的合并代价为 O ( n l o g n ) O(n log n) O(nlogn),而算法整体的时间复杂度则会退化成为 O ( n l o g 2 n ) O(n log_2 n) Onlog2n,并不是真正意义上的 O ( n l o g n ) O(n log n) O(nlogn)

  2. 在设计算法的过程中,可以利用蛮力求解的方式在小规模的数据验证算法的正确性

  3. 利用计算机的时钟作为种子产生的随机数来生成点的坐标会产生大量的重复,可以利用STL库中的set容器自己设置去重的规则进行去重,还可以获取cpu运行周期作为随机数产生的种子使得生成的随机数较为随机

  4. 灵活应用数学定理以辅助设计算法可以使得算法的时间复杂度获得极大的提升,如上面合并过程只需枚举6个点的证明过程,就使合并代价大大降低,数学工具是设计算法的利器

期末大作业题目 1.结合所学相关内容,研究撰写一篇关于云计算资源分配策略或任务调度或资源使用预测算法的论文。要求扩展云计算仿真器CloudSim或其它仿真软件设计实现该算法,并进行仿真实验测试和分析该算法/策略的性能。也可以是将云计算技术应用于自己感兴趣研究方向为主题的研究论文。论文撰写格式要求以《软件学报》的投稿要求为模板。 摘 要: 粒子群优化(PSO)算法思想来源于人工生命和演化进化论。PSO 通过粒子追随自 己找到的最优解和整个群体的最优解来完成优化,群体中每一个粒子代表问题的一个候选解, 属于一类启发式随机全局优化技术。PSO 的优势在于简单又功能强大。本文将使用云计算仿 真器 CloudSim 实现 PSO 完成任务调度以及改进算法评估性能。 关键词: 粒子群;优化;进化论;CloudSim 中图法分类号: Particle swarm optimization algorithm and improved implementation CHEN Jia-Le1 1(School of Computer Science and Software, Shenzhen University, Shenzhen 518000, China) Abstract: The idea of particle swarm optimization (PSO) comes from artificial life and evolutionary theory. Particle swarm optimization (PSO) is a heuristic stochastic global optimization technique, in which each particle represents a candidate solution of the problem. The advantage of PSO is simple and powerful. In this paper, we will use the cloud computing simulator cloudsim to implement PSO to complete task scheduling and improve the algorithm to evaluate performance. Key words: particle swarm; optimization; evolutionism; CloudSim;
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值