分治算法 最接近点对(一维)

介绍一种在一维空间寻找最近点对的有效算法,并通过示例代码展示如何实现该算法。该算法首先对点进行排序,然后采用分治策略递归地找到最近点对。

最接近点对,在实际应用中有很强的实用性!下面我就介绍一下,怎么求一维的最接近点!二维的会再下一次博客更新!


方法:把所有点从大到小先进行排序,找出最大点MAX和最小点min。然后求mid=(max+min)/2,以mid为 参照点把集合s分成S1和S2.如图:



(1)

有上图可知,最小点对可能存在于S1或S2中的一对点,不妨设这对点的距离是d,还有一种可能就是一个点存在于S1中,一个点存在于S2中,根据已经做好的排序可知,这两个点必定是S1中的最大点p,和S2中的最小点q,所以我们只需要比较(q-p)和d的大小,然后迭代返回,即可。

声明:本篇博客是参考http://blog.csdn.net/liufeng_king/article/details/8484284这个写的!如果想知道具体的细节,请参考上述网址!下面我附上源代码,只是把上述的代码做了一点变化!(本来想附上java代码,但java代码没有调试成功!遗憾!)
//2d10-1 一维最邻近点对问题
#include <ctime>
#include <stdlib.h>
#include <math.h>
#include <iostream>
using namespace std;

const int L=100;
//点对结构体
struct Pair
{
	float d;//点对距离
	float d1,d2;//点对坐标
};
float Random();
int input(float s[]);//构造S
float Max(float s[],int p,int q);
float Min(float s[],int p,int q);
template <class Type>
void Swap(Type &x,Type &y);
template <class Type>
int Partition(Type s[],Type x,int l,int r);
Pair Cpair(float s[],int l,int r);

int main()
{
	int m;
	float s[L];
	Pair d;
	m=input(s);
	d=Cpair(s,0,m-1);
	cout<<endl<<"最近点对坐标为: (d1:"<<d.d1<<",d2:"<<d.d2<<")";
	cout<<endl<<"这两点距离为: "<<d.d<<endl;
	return 0;
}


float Random()
{
	float result=rand()%10000;
	 return result*0.01;
}

int input(float s[])
{
	int length;
	cout<<"输入点的数目: ";
	cin>>length;
	cout<<"点集在X轴上坐标为:";
	for(int i=0;i<length;i++)
	{
		s[i]=Random();
		cout<<s[i]<<" ";
	}

	return length;
}


float Max(float s[],int l,int r)//返回s[]中的最大值
{
	float s_max=s[l];
	for(int i=l+1;i<=r;i++)
		if(s_max<s[i])
			s_max=s[i];
	return s_max;
}

float Min(float s[],int l,int r)//返回s[]中的最小值
{
	float s_min=s[l];
	for(int i=l+1;i<=r;i++)
		if(s_min>s[i])
			s_min=s[i];
	return s_min;
}

template <class Type>
void Swap(Type &x,Type &y)
{
	Type temp = x;
	x = y;
	y = temp;
}

template <class Type>
int Partition(Type s[],Type x,int l,int r)
{
	int i = l - 1,j = r + 1;

	while(true)
	{
		while(s[++i]<x && i<r);
		while(s[--j]>x);
		if(i>=j)
		{
			break;
		}
		Swap(s[i],s[j]);
	}
	return j;
}

//返回s[]中的具有最近距离的点对及其距离
Pair Cpair(float s[],int l,int r)
{
	Pair min_d={99999,0,0};//最短距离

	if(r-l<1) return min_d;
	float m1=Max(s,l,r),m2=Min(s,l,r);

	float m=(m1+m2)/2;//找出点集中的中位数

	//将点集中的各元素按与m的大小关系分组
	int j = Partition(s,m,l,r);

	Pair d1=Cpair(s,l,j),d2=Cpair(s,j+1,r);//递归
	float p=Max(s,l,j),q=Min(s,j+1,r);

	//返回s[]中的具有最近距离的点对及其距离
	if(d1.d<d2.d)
	{
		if((q-p)<d1.d)
		{
			min_d.d=(q-p);
			min_d.d1=q;
            min_d.d2=p;
			return min_d;
		}
		else return d1;
	}
	else
	{
		if((q-p)<d2.d)
		{
			min_d.d=(q-p);
			min_d.d1=q;
            min_d.d2=p;
			return min_d;
		}
		else return d2;
	}
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值