经典算法:最短点对

本文旧文新发,介绍了最短点对算法的测试与改进。测试采用三种解法对比结果及小数据人工排查,暴力法适用于小数据。改进方面,暴力算法复杂度为O(n2),改进型先按Y排序,只比较特定点对。实验表明,500万数据以下改进算法明显优于经典算法,1000万数据时略强。

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

                                                                          软件架构师何志丹

说明

旧文新发,改了错别字,死链等。尽量保持“原汁原味”。

难点

如何测试。我的解决方式是:a,三种解法,看结果是否一致。b,小数据(100个点),人工排查。第一种方法,暴力法适合小数据。第二种方法:我的改进型。第三种方法:经典方法(分治法)。实验证明1000万数据时,我的算法有优势。

改进


暴力算法,O(n2)。我的改进型要点:先对所有数据按Y排序。只比较y距离小于等于已知最小距离的点对。经典方法:按Y排序,分成两部分,递归调用。合并时只比较距离分界线不超过已知最小距离的点对。
实际证明500万数据以下,我的改进算法明显优于经典算法;1000万数据时,略强于经典算法。

核心源码节选:

double Dis(const CPT& pt1,const CPT& pt2)
{
	return sqrt((double) (pt1.x-pt2.x)*(pt1.x-pt2.x)+(pt1.y-pt2.y)*(pt1.y-pt2.y)+(pt1.z-pt2.z)*(pt1.z-pt2.z) );
}

void InitData(CPT* pts,int iNum)
{
	srand(time(NULL));

	for( int i = 0 ; i < iNum ; i++)
	{
		pts[i].x = rand()%10000;
		pts[i].y = rand()%10000;
		pts[i].z = rand()%10000;
	}
}

double Fun1(CPT* pts,const int iNum)
{
	 double dMinDis = 10000*10000 ;
	for(int i = 0 ; i < iNum ; i++ )
		for( int j = i+1 ; j < iNum ; j++ )
		{
			const double d = Dis(pts[i] , pts[j]);
			if( d < dMinDis)
			{
				dMinDis = d ;
			}
		}
		return dMinDis;
}

class CCmpY
{
public:
	bool operator()(const CPT& pt1,const CPT& pt2)
	{
		return pt1.y < pt2.y ;
	}
};

double Fun2(CPT* pts,const int iNum)
{
	std::sort(pts,pts+iNum,CCmpY() );

	double dMinDis = 10000*10000 ;
	for(int i = 0 ; i < iNum ; i++ )
		for( int j = i+1 ; j < iNum ; j++ )
		{
			const double d = Dis(pts[i] , pts[j]);
			if( d < dMinDis)
			{
				dMinDis = d ;
			}
			if( abs(pts[i].y - pts[j].y )> dMinDis )
			{
				break;
			}
		}
		return dMinDis;
}

double Fun3(CPT* pts,const int iNum)
{
	std::sort(pts,pts+iNum,CCmpY() );

	if( iNum < 100 )
	{
		return Fun1(pts,iNum);
	}

	const int iMid = iNum/2 ;
	const double dMin1 = Fun3(pts,iMid);
	const double dMin2 = Fun3(pts+iMid,iNum-iMid);
	double dMinDis = min(dMin1,dMin2) ;
	for(int i = iMid-1 ; i >= 0 ; i-- )//左集合
	{
		if( abs(pts[i].y - pts[iMid].y ) > dMinDis )
		{
			break;
		}
		for( int j = iMid ; j < iNum ; j++ )//右集合
		{
			const double d = Dis(pts[i] , pts[j]);
			if( d < dMinDis)
			{
				dMinDis = d ;
			}
			if( abs(pts[i].y - pts[j].y )> dMinDis )
			{
				break;
			}
		}
	}
		return dMinDis;
}

测试环境

似乎是WinXP VS2005(VC8)

下载

可通过以下链接下载测试数据,exe,源码(VS2005,VC8)
https://download.youkuaiyun.com/download/he_zhidan/10887801

https://img-blog.csdnimg.cn/ea2601b3918f4aef836b5fe30da2ebf7.gif#pic_center#pic_center

其它

学院课程

基础算法的C++实现课程,请点击下面的优快云学院的链接。讲义有算法详解。

2024年1月15之前完全免费,之后绝大部分免费

https://edu.youkuaiyun.com/course/detail/38771

C#入职培训

此课程的目的:让新同事更快完成从学生到C#程序员的转换,更快上手完成C#的开发工作。

https://edu.youkuaiyun.com/course/detail/38768

C++入职培训

让新同事更快完成从学生到C++程序员的转换,更快上手完成C++的开发工作。

https://edu.youkuaiyun.com/course/detail/32049

运行验证环境

Win10 VS2022 Ck++17 或win7 VS2019 C++17

每天都补充正能量

好好学习,天天向上。

事无终始,无务多业。

是故置本不安者,无务丰末。

相关下载

如果你时间宝贵,只想看精华,请到优快云下载频道下载《闻缺陷则喜算法册》doc版

https://download.youkuaiyun.com/download/he_zhidan/88348653

https://i-blog.csdnimg.cn/blog_migrate/4b48f80cdf99b7ea9bda88ceb91d788f.gif#pic_center

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

软件架构师何志丹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值