源代码:

深大算法设计与分析实验二——分治法求最近点对问题代码-C/C++文档类资源-CSDN下载

目录

实验问题

一、实验目的:

二、内容:

三、算法思想提示

产生不重复的随机点算法:

蛮力算法:

分治算法

数据分析:

实验结论:


实验问题

一、实验目的:

  1. 掌握分治法思想。
  2. 学会最近点对问题求解方法。

二、内容:

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

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

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

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

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

三、算法思想提示

1.  预处理:根据输入点集S中的x轴和y轴坐标进行排序,得到X和Y,很显然此时X和Y中的点就是S中的点。

2.  点数较少时的情形

3.  点数|S|>3时,将平面点集S分割成为大小大致相等的两个子集SL和SR,选取一个垂直线L作为分割直线,如何以最快的方法尽可能均匀平分?注意这个操作如果达到θ(n2)效率,将导致整个算法效率达到θ(n2)

4.  两个递归调用,分别求出SL和SR中的最短距离为dl和dr。

5.  取d=min(dl, dr),在直线L两边分别扩展d,得到边界区域Y,Y’是区域Y中的点按照y坐标值排序后得到的点集(为什么要排序?),Y'又可分为左右两个集合Y’L和Y’R

6.  对于Y’L中的每一点,检查Y’R中的点与它的距离,更新所获得的最近距离,注意这个步骤的算法效率,请务必做到线性效率,并在实验报告中详细解释为什么能做到线性效率?

方法:蛮力法、分治法。

产生不重复的随机点算法:

首先能想到的是产生一个点就与前面产生的点一一比较看是否重复,但是当数据量十分庞大的时候需要很多的时间。既然这样时间复杂度会很大,那么我就用增大空间复杂度来减小时间复杂度。由于C++语言中的rand函数最大产生的数字不会超过40000,于是我开了一个大小为40000×40000的布尔型数组用于记录点是否被使用。首先将这个二维数组的所有值设位false代表没有被设定,若产生一个点且之前没有产生过,则将产生点的x,y坐标作为布尔型二维数组的下标,将对应的这个数值改为true,如果之前有产生过,则重新获取一个数。

伪代码如下:

Creat_Random_Point (P,n)for i=0 to 40000for j=0 to 40000Prevent[i][j]=falsefor i=0 to nxtemp=rand   ytemp=randif Prevent[xtemp][ytemp]==truei--elseP[i].set(xtemp,ytemp)Prevent[xtemp][ytemp]=true

蛮力算法:

蛮力法就是将平面上的所有点对进行一一计算距离,并与最短的哪个距离依次进行比较,找到那个最短的距离。

伪代码如下:

Slow_FindPoint (P, n, Min)
Min=Distance(P[0],P[1])
for i=1 to n-1for j=i+1 to nif  Distance(P[i],P[j])<MinMin= Distance(P[i],P[j])

我们可以看到这里面有两个for循环而且一个到n-1一个到n,所以这个时间复杂度是的。

分治算法

分治法可以将问题缩小化,将庞大的问题逐渐缩小成单个小的问题进行解决。

在寻找点当中,先将点集按照x轴方向排序,我们将使用快速排序进行排序,这个时间效率是

接着将问题分治,利用递归来进行分治。找到x轴的中轴线将点一分为二,同理得到的两个区域也向上述描述一样一分为二,直到分到只有一个点或者两个点。

当只有一个点时,将最小的值设置为无穷大,若是只有两个点,则将最小值设    为这两个点的距离。

接下来进行合并操作。

伪代码如下:

接下来是需要考虑合并算法,我们需要将算法尽量做到线性。

方法1:分治完毕后我们     得到了两侧最小的距离,先比较哪一个   更小,并记为。因为不一定这个距离是最短的距离,有可能在分界处两端的点的    距离是最短的,所以我们需要考虑到这一部分。但是我们也不能让这两个点依次比    较,因为这样算法效率是的,所以需要缩小遍历的数量。

以两侧合并的中线为基点,分别向两端扩展的距离,在这个区域之内的点的两点距离是有可能比更小的,如果将这两点依次比较,如果数据比较极端的话也会将算法效率降低到,所以还要加以限制。

于是在比较每一个点的时候,将y轴方向距离小于的点进行,大于就不用比较了,我们可以证明这样一个点比较的数量不大于5个。且范围内的点最多只有6个。

如上图,我们取极端的情况,若两个点正好在这个的正方形的中点处时,画一个半径为的圆,我们可以观察到只有四个地方可以放点,所以说一个点最多与另外5个点进行比较,于是将的效率降低到了

那么需要查找上下为的点我们应该怎么寻找呢?最简单的形式是将中间区域的所有点放在一个数组当中,然后延y轴从下至上进行排序,然后按顺序从下至上进行比较,这样可以遍历到所有的点。由于是从下至上进行比较,不用返回去进行比较,那么每个开始点比较的次数又可以减小。

如图所示,因为是从下至上进行比较,那么下方的点将可以不用再进行比较,于是一个点开始时只需要跟另外三个点进行比较,比较次数时肯定小于的。

接下来要开始考虑如何对点进行y轴排序,一开始我的想法是将点放在一个临时数组里面,并记下来点的下标,然后进行快速排序。如此一来最坏的情况合并算法效率就会是

伪代码如下:

 Merge (P,l,m,h,Min)for indexL=m to lif P[m].x-P[indexL].x>Minbreakfor indexH=m to hif P[indexH].x-P[m].x>Minbreak;n=indexH-indexL+1if n>=2let P[indexL ... indexH] to temp[0…n]sort(temp)for i=0 to nfor j=i+1 to nif temp[i].y-temp[j].y>Minbreakif Distance(temp[i],temp[j])<MinMin= Distance(temp[i],temp[j])

前面两个for循环是为了找到中间的范围内点的下标范围,记为indexL和indexH。当在范围内的点是大于或等于2才需要进行比较。接着将数据放入临时数组并且进行排序。后面两个for循环是用于比较各个点。这样下来最多的计算次数将会是,那么合并算法的效率是

用主定理法计算整个算法效率。

由于不是在多项式意义上的大于,所以无法用主定理法。

利用递归树:

所以

显然这不是最快的算法。

于是要想将效率提高到就不能再合并算法中进行排序,那么我们可以运用合并排序在合并的同时进行将所有点进行延y轴排序。

同样的取一个临时数组,点的下标存放在临时数组当中。将原来的合并函数当中的排序函数删除并且在if语句之前加上合并排序的合并函数,再遍历这个临时数组,将下标在范围内的点下标找到再放入一个临时数组中。伪代码如下:

 Merge (P,l,m,h,Sorted_tp,tp1,tp2,Min)for indexL=m to lif P[m].x-P[indexL].x>Minbreakfor indexH=m to hif P[indexH].x-P[m].x>Minbreak;MergeSort_Merge(Sorted_tp,tp1,tp2)index=0for i=0 to h-l+1if indexL<=Sorted_tp[i].No<=indexHtemp[index++]=Sorted_tpn=indexH-indexL+1if n>=2for i=0 to nfor j=i+1 to nif temp[i].y-temp[j].y>Minbreakif Distance(temp[i],temp[j])<MinMin= Distance(temp[i],temp[j])

此时在最坏的情况下,运行次数大概是,该合并算法的效率是

同时这个算法相较于上一个算法来说,必须有两次运行到,而上一个算法是数据量极端的时候才有到。如果将最大次数定位不确定的次数定位,则第一个合并算法的次数是:。第二个合并算法的次数是。所以在数据量小且理想的情况下,第一个合并算法的效率也许会小于第二个合并算法,但是由于第一个合并算法的效率是,当数据量十分庞大的时候还是第二个合并算法效率更高一点。

我们用主定理方法计算第二个分治算法的效率:

∴符合情况2

数据分析:

蛮力算法运行结果如下:

我们可以清楚的看到这个曲线呈现的是二次曲线,我运行的是10000到100000的数据量,当到100000数据量时,蛮力法需要53.515秒的时间,而10000数据量时需要0.543秒的时间,正好相差100倍。

第一个效率为的分治算法结果如下:

        可以看到这个分治法虽然效率不是但是依然比蛮力法快很多。这是以数据量在十万到一百万之间的数据,可以明显地看到比蛮力法快很多。相同十万个数据蛮力法需要53秒而分治法只需要0.073秒。

第二个效率为的分治算法结果如下:

        可以看到数据基本与曲线拟合,且比蛮力法快很多。

接下来我们对比一下两个分治算法的效率。

        我们可以看到在数据量小的时候甚至效率在的分治算法用时(0.073秒)还比效率在的合并算法用时(0.079秒)要短,这就是我上述所说的有可能数据量小的时候第一个合并算法的用时要比第二个短。但是到了后面数据量大的时候明显第一个分治算法用时要多了。

我们将数据量继续扩大。

        明显的第一个分治算法要比第二个慢了,效率为的算法在1000万数据量时用时8.646秒,效率为的算法在1000万数据量用时12.135秒。

实验结论:

本次实验体会到了分治法的有点和算法思想,他的主要思想就是将大问题缩小化,并且将尽可能的提高合并效率,合并的效率最好是线性的。本次实验我一开始没有掌握到分治法的精髓之处,没有将合并效率降低到线性,而是将合并效率达到了o(nlgn)。于是导致了整个合并算法不是最佳的。也许在小数据量的时候并不能体会到这个差距但是当数据量十分庞大的时候就可以发现这个差距是很大的了。

深大算法设计与分析实验二——分治法求最近点对问题相关推荐

  1. 算法设计与分析 实验二 分治法求解最近点对问题

    分治法求解最近点对问题 一.实验目的与要求 1.实验基本要求 2.实验亮点 二.实验内容与方法 三.实验步骤与过程 (一)一些准备工作 1.实验流程 2.数据生成与去除重复点 (二)暴力穷举法 1.算 ...

  2. 【算法设计与分析】关于分治法的一些(伪)代码整理

    分治法 合并排序 利用分治法求一个元素在数组中的最大位置 利用分治法求一个n元素数组的最大元素和最小元素的值 是否稳定 快速排序 合并排序 利用分治法求一个元素在数组中的最大位置 伪代码: MaxIn ...

  3. 算法设计与分析 实验二 贪心算法

    实验2.<贪心算法实验> 一.实验目的 了解贪心算法思想 掌握贪心法典型问题,如背包问题.作业调度问题等. 二.实验内容 编写一个简单的程序,实现单源最短路径问题. 编写一段程序,实现找零 ...

  4. 算法设计与分析实验二:动态规划法实现TSP问题和0/1背包问题

    [实验目的] 1.熟练掌握动态规划思想及教材中相关经典算法. 2.使用动态规划法编程,求解0/1背包问题和TSP问题. TSP问题 一.实验内容: TSP问题是指旅行家要旅行n个城市,要求每个城市经历 ...

  5. 太原理工大学linux与python编程r实验报告_太原理工大学算法设计与分析实验报告...

    <太原理工大学算法设计与分析实验报告>由会员分享,可在线阅读,更多相关<太原理工大学算法设计与分析实验报告(12页珍藏版)>请在人人文库网上搜索. 1.本科实验报告课程名称: ...

  6. C/C++ 算法设计与分析实验报告

    算法设计与分析实验报告 算法实验整体框架的构建 菜单代码块 选择函数代码块 主函数代码块 实验模块Ⅰ:算法分析基础--Fibonacci序列问题 实验解析 Fibonacci序列问题代码块 实验模块Ⅱ ...

  7. 计算机算法设计与分析 动态规划 实验报告,动态规划法解最长公共子序列(计算机算法设计与分析实验报告).doc...

    动态规划法解最长公共子序列(计算机算法设计与分析实验报告) 实报 告 实验名称:任课教师::姓 名:完成日期:二.主要实验内容及要求: 要求按动态规划法原理求解问题: 要求交互输入两个序列数据: 要求 ...

  8. 格雷码算法c语言实验报告,算法设计与分析实验报告

    本科生实验报告 课程名称:算法设计与分析 实验项目:递归和分治算法 实验地点:计算机系实验楼110 专业课:物联网1601学生.2016002105 学生姓名:于 指导员:郝晓丽 2018年5月4日 ...

  9. 算法设计与分析实验指导(完整版)

    算法设计与分析实验指导 文章目录 算法设计与分析实验指导 1. 快速排序及第k小数 1.1 快速排序 1.1.1 Implementation 1 1.1.2 算法特性分析 1.1.3 Improve ...

最新文章

  1. HTML5与jQuery实现渐变绚丽网页图片效果
  2. day13-(事务mvc反射补充)
  3. 如何在 Windows 主机上访问本地局域网中的 Linux 主机
  4. linux 转码软件,分享|Linux 桌面中 4 个开源媒体转换工具
  5. mac mysql root不能登陆_Mac下新安装的MySQL无法登陆root用户解决方法
  6. 【ICLR2021必读】 【自监督学习】 【Transformer】相关论文
  7. php获取内容中第一张图片地址
  8. python tkinter:单位换算小工具完整代码
  9. 基于三菱PLC的两轴圆弧插补
  10. yaml数组解析_YAML语法介绍
  11. 实习日记——工程配置
  12. PowerDesigner工具栏消失恢复
  13. Spring Boot入门教程(四十):微信支付集成-刷卡支付
  14. Vue学习笔记01-基础部分
  15. Rk3399—添加usb转串口驱动
  16. [个人笔记]操作系统复习笔记
  17. 新型勒索软件Phobos利用弱安全性攻击目标
  18. 继承(extends)
  19. AFNetworking源码学习 1
  20. PHP反弹shell

热门文章

  1. Ubuntu\linux,加载mcp2515的驱动,链接mcp2515,mcp2515的这个驱动默认在linux内核中。jetson nao、香橙派、树莓派
  2. (附源码)计算机毕业设计ssm高校体育馆管理信息系统
  3. matlab2019b 读取excel数据并转换成.mat文件
  4. 基于springboot的少儿识字系统
  5. 一元多项式加法c语言,C语言一元多项式加法.doc
  6. 分布式通信协议-序列化(分布式笔记)
  7. BP(商业计划书写)
  8. 使用st-link+keil下载和调试华大单片机的教程
  9. 全国所有城市当天天气数据爬虫
  10. Python用pydicom库读取dicom文件