【算法设计与分析】分治法(最近点对问题)

这篇具有很好参考价值的文章主要介绍了【算法设计与分析】分治法(最近点对问题)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

实验目的

实验内容与结果

蛮力法求解

分治法求解

实验总结


  • 实验目的

(1)掌握分治法思想。

(2)学会最近点对问题求解方法。

  • 实验内容与结果

蛮力法求解

算法过程:

遍历n个点与剩余n-1个点之间的距离,在计算点对距离时不断更新最短距离的值,遍历完所有点对后即可求得最短点对距离。

伪代码:

最近点对算法,算法设计与分析,算法,机器学习,数据结构

复杂度分析:

需要对n(n-1)/2个点对进行遍历来求得最小点对距离,最好情况、最坏情况和平均情况的时间复杂度都为O(n²)。

测试算法运行时间:

随机生成N个点的平面坐标,将每个点的x和y坐标值限制在1-100的范围内,分别对N = 100000-1000000统计算法运行时间,并比较理论效率与实测效率的差异。

理论效率计算:

T实测 = k * n实测²

T理论 = k * n理论²

  • T理论 = T实测 * (n理论/n实测)²

最终结果如下:(理论效率以N=100000为基准)

N 100000 200000 300000 400000 500000
实测效率/s 79.076 316.686 709.958 1258.56 1972.48
理论效率/s 79.076 316.304 711.684 1265.216 1976.9

N

600000 700000 800000 900000 1000000
实测效率/s 2848.37 4214.7 5090.44 6665.26 8409.58
理论效率/s 2846.736 3874.724 5060.864 6405.156 7907.6

最近点对算法,算法设计与分析,算法,机器学习,数据结构

分治法求解

算法过程:

算法每一次递归调用的输入为点集S以及数组X和Y,X和Y数组中分别包含S中所有点的x和y坐标。在划分开始前,对数组X和Y中的点排序,使其x和y坐标值单调递增。

检查是否有| S | <= 3成立,如果有,则采用暴力方法求解:对所有点对进行检查,并返回最近点对距离。

最近点对算法,算法设计与分析,算法,机器学习,数据结构

对应代码如下:

if (end == start){
        return DBL_MAX;
    }//递归出口(只含一个点时)
    if (end - start == 1){
        return getDistance(p[end],p[start]);
    }//只含两个点时 直接返回两点距离
    if (end - start == 2){
        return brutalSort(p,3);
    }//含三个点时 直接用蛮力法求解

如果| S | > 3,则递归调用如下分治模式。

分解:在分治开始前,已经对X和Y数组进行递增排序,此时取中间点将点集划分为左区域SL和右区域SR,SL中所有点都在中线上或是在中线的左侧,SR中所有点都在中线上或是在中线的右侧。此时要想以最快的方法尽可能均匀平分,可采用效率较高的快速排序和合并排序算法,时间复杂度为O(nlogn)

最近点对算法,算法设计与分析,算法,机器学习,数据结构

             

       解决:划分后进行两次递归调用,一次找出SL中的最近点对距离dL,另一次找出SR中的最近点对距离dR。令SL和SR返回的最近点对距离分别为dL和dR,并且取d = min(dL,dR)。

最近点对算法,算法设计与分析,算法,机器学习,数据结构

对应代码如下:

double d = DBL_MAX;
    int mid = start + (end - start) / 2;
    double d1 = divide(p,n,start,mid);//递归得到左半区的最近点对距离
    double d2 = divide(p,n,mid + 1,end);//递归得到右半区的最近点对距离
    d = min(d1,d2);

       合并:考虑最近点对有可能是上述某次递归调用找出的距离为d的点对,也有可能是SL中的一个点与SR中的一个点形成的点对。寻找是否存在距离小于d的一个点对,一个点位于SL中,另一个位于SR中。若存在这样一个点对,则其中两个点与直线L的距离都必须在d的范围内。

最近点对算法,算法设计与分析,算法,机器学习,数据结构

同时这两点在垂直方向上的距离也应小于d。因此可以限制该点对的范围在2d*d的方框内。

最近点对算法,算法设计与分析,算法,机器学习,数据结构

建立一个数组Y’,它是边界区域Y中的点按照y坐标值排序后得到的点集,Y’可划分为Y’L和Y’R左右两个集合。沿y轴方向找出最短距离,通过排序的贪心策略更容易实现。

对应代码如下:

Point* y = new Point[n];//对应Y'
    int pos = 0;
    Point* yl = new Point[n];//对应Y'L
    int posl = 0;
    Point* yr = new Point[n];//对应Y'R
    int posr = 0;
    for (int i = start; i <= end; i++){
        if (fabs(p[i].x - p[mid].x) <= d){
            y[pos++] = p[i];
            if (p[mid].x - p[i].x <= d){
                yl[posl++] = p[i];
            } else if (p[i].x - p[mid].x <= d){
                yr[posr++] = p[i];
            }
        }
    }
    sort(y,y + pos, cmpy);

对于Y’L中的每一点,检查Y’R中的点与它的距离,更新所获得的最近距离。

部分蛮力:遍历一点在Y’L中,另一点在Y’R中的所有点对距离,并返回得到的最小点对距离。此方法的时间复杂度为O(n²),不符合线性效率,故舍弃。

一趟查询:考察合理范围内的左半边d*d正方形,因为Y’L中所有点之间至少相距距离d,所以该正方形内至多有4个点满足该条件。类似地,Y’R中也有4个点满足该条件。因此,Y’中至多有8个点可能位于该d*2d范围内。(直线上的点可能属于Y’L也可能属于Y’R,因此直线上至多有4个点)。因此,只需要查询Y’L中每个点随后的6个点,即可达到线性效率并计算出合法区域内的最小点对距离。

最近点对算法,算法设计与分析,算法,机器学习,数据结构

对应代码如下:

for (int i = 0; i < pos - 6; ++i) {
        for (int j = i + 1; j <= i + 6 && y[j].y - y[i].y <= d; ++j) {
            double dis = getDistance(p[i],p[j]);
            if (dis < d){
                d = dis;
            }
        }
    }

程序正确性验证:

对同一组数据分别进行蛮力法和分治法进行求解,运行结果如下:

最近点对算法,算法设计与分析,算法,机器学习,数据结构

返回值为最近点对距离,两方法求得结果相同,程序正确性得证。

时间复杂度分析:

在该算法中,最坏情况、最好情况和平均情况的时间复杂度都为O(nlogn)

测试算法运行时间:

随机生成N个点的平面坐标,将每个点的x和y坐标值限制在1-100的范围内,分别对N = 100000-1000000统计算法运行时间,并比较理论效率与实测效率的差异。

理论效率计算:

T实测 = k * n实测logn实测

T理论 = k * n理论logn理论

  • T理论 = T实测 * n理论logn理论 / n实测logn实测

最终结果如下:(理论效率以N=100000为基准)

N

100000 200000 300000 400000 500000
实测效率/s 1.088 3.458 5.778 6.484 9.971
理论效率/s 1.088 2.307 3.575 4.876 6.2
N 600000 700000 800000 900000 1000000
实测效率/s 10.723 11.093 11.532 14.897 18.473
理论效率/s 7.544 8.903 10.276 11.660 13.056

最近点对算法,算法设计与分析,算法,机器学习,数据结构


  • 实验总结

由本次实验可知,分治法效率远远高于蛮力法的效率,蛮力法的时间复杂度为O(n²),分治法的时间复杂度为O(nlogn)。文章来源地址https://www.toymoban.com/news/detail-720799.html

到了这里,关于【算法设计与分析】分治法(最近点对问题)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 算法分析与设计考前冲刺 (算法基础、数据结构与STL、递归和分治、 动态规划、贪心算法、 回溯算法)

    算法分析与设计考前冲刺 算法基础 算法是一系列解决问题的清晰指令,代表着用系统的方法描述解决问题的策略机制。 程序是算法用某种程序设计语言的具体的 具体实现 算法特征: 有穷性(有限步) 确定性 输入 输出 可行性(有限时间) 算法的复杂性: 时间复杂性 和空间复

    2024年02月02日
    浏览(33)
  • 算法:分治思想处理归并递归问题

    利用归并思想进行分治也是很重要的一种思路,在解决逆序对的问题上有很大的需求空间 于是首先归并排序是首先的,归并排序要能写出来: 以上为归并排序基本算法原理,基于这个原理可以解决逆序对问题,逆序对问题通常问法是,给定某一个数据,在整个数组中找比这

    2024年02月10日
    浏览(33)
  • C++:分治算法之输油管道问题

    目录 描述 输入 输出 输入样例 输出样例 分析 代码 运行结果 ¢ 某石油公司计划建造一条 由东向西 的主输油管道。该管道要穿过一个有 n 口油井的油田。从每口油井都要有一条输油管道沿最短路经(或南或北)与主管道相连。 ¢ 如果给定 n 口油井的位置,即它们的 x 坐标(

    2024年02月02日
    浏览(29)
  • (软考-软件设计师.下午)动态规划算法、回溯算法、贪心算法、分治算法的应用

    :【递归技术】【二分查找】 分治法的设计思路: 将一个难以直接解决的 大问题 分解成一些 规模较小 的相同问题以便于 逐个击破,分而治之 。      由代码可以看出二分查找也属于分治法的一种,关于二分查找,这位博主总结的很详细。  :【查表】   动

    2024年02月06日
    浏览(34)
  • 机器学习和大数据:如何利用机器学习算法分析和预测大数据

      近年来,随着科技的迅速发展和数据的爆炸式增长,大数据已经成为我们生活中无法忽视的一部分。大数据不仅包含着海量的信息,而且蕴含着无数的商机和挑战。然而,如何从这些海量的数据中提取有价值的信息并做出准确的预测成为了许多企业和研究机构亟需解决的问

    2024年02月06日
    浏览(45)
  • 机器学习基础算法--回归类型和评价分析

    目录 1.数据归一化处理 2.数据标准化处理 3.Lasso回归模型 4.岭回归模型 5.评价指标计算       MSE= i=1 n ( Y i - Y ^ ) 2 n RMES= i=1 n ( Y i - Y ^ ) 2 n MAE= i=1 n | Y i - Y ^ | n R 2 =1- i=1 n ( Y ^ - Y i ) 2 i=1 n ( Y ¯ - Y i )2

    2024年02月09日
    浏览(23)
  • 分治与减治算法实验:题目6 淘汰赛冠军问题

    目录 前言 实验内容 实验流程 实验分析 实验过程 流程演示 写出伪代码 实验代码 运行结果 改进算法 总结 淘汰赛冠军问题是一个经典的算法设计与分析的问题,它要求我们在给定的n个参赛者中,通过一系列的比赛,找出最终的冠军。这个问题可以用分治策略来解决,即将

    2024年02月06日
    浏览(139)
  • C++分治(分而治之)算法:将复杂问题化繁为简

    导语: 在计算机科学领域,分治算法是一种常见且强大的问题求解方法。它将一个复杂的问题分解成若干个规模较小且相互独立的子问题,并通过递归地解决这些子问题来得到最终的结果。本文将介绍C++中实现分治算法的基本原理及示例,帮助读者更好地理解和应用这一算法

    2024年01月25日
    浏览(34)
  • 分治与减治算法实验: 排序中减治法的程序设计

    目录 前言 实验内容 实验目的 实验分析 实验过程 流程演示 写出伪代码 实验代码 代码详解 运行结果 总结 本文介绍了算法实验排序中减治法的程序设计。减治法是一种常用的算法设计技术,它通过减少问题的规模来求解问题。减治法可以应用于排序问题,例如插入排序、选

    2023年04月27日
    浏览(25)
  • 分治与减治算法实验:题目2 排序中分治法的程序设计

    目录 前言: 一、实验内容 二、实验目的 三、实验步骤 四、实验过程 1、算法分析 2、写出伪代码 3、代码实现 4、代码详解 5、用例测试 6、复杂度分析 总结 分治法是一种将复杂问题分解为若干个相同或相似的子问题,然后递归地求解子问题,最后将子问题的解合并为原问题

    2023年04月25日
    浏览(28)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包