真正的平面上最近点对的n log(n)算法

平面上一堆二维坐标点,找其中两点间的最小距离,这个问题网上一大把n log(n) * log(n)的方法,这些算法的典型例子 http://yzmduncan.iteye.com/blog/1432880 ,原因是在求得中心线两边的最小距离s后,都要对处于中线左右两边s距离以内的点按y坐标排序,这种方法不是n log(n)复杂度(参见维斯在“数据结构与算法分析,c语言版”,中文版p281),要是n log(n)复杂度,要在递归之前就对点按y坐标排序,网上少见这种算法的源码,其中一个似乎有些问题的代码见tge7618291的博客 http://blog.csdn.net/tge7618291/article/details/4753126?reload#comments, 但他在递归中反复利用同样两个事先已经按x, y坐标排好序的p, q数组,这样就不用分配新内存,但是不太好理解,另外,更糟糕的是,他的源代码编译后的程序执行,我发现了一组和最普通的n平方算法标准答案不一样的一组数据点我留言给作者,但作者似乎已经废弃了他的博客。。。

        我按照 算法导论和维斯在“数据结构与算法分析,c语言版”上介绍的思想,实现了n log(n)复杂度算法,即:递归之前按x, y坐标排好序X, Y数组, 作为参数,其后每次递归调用里把Y数组中每个点按在中心线的左右两边分成YL, YR子数组(每个子数组仍然按y坐标排序), 把这两个数组分别传人对左右两边的子递归的函数中,而X数组保持不变,这样就比tge7618291的代码好理解,代码如下

// p280_nearestPtPair.cpp : 定义控制台应用程序的入口点。
<pre name="code" class="cpp">// nearPts_ZHENGLI.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "stdafx.h"
#include <stdlib.h>
//#include <iostream>
//#include <cstdio>
//#include <cstring>
#include <cmath>
#include <stack>
#include <list>
using namespace std;


// 似乎http://blog.csdn.net/lu1012123053/article/details/9825175方法也是n log(n)算法 ,但没细看
// 下面方法部分代码 参考了 http://blog.csdn.net/tge7618291/article/details/4753126?reload#comments
#define min(a,b)    (((a) < (b)) ? (a) : (b))
typedef struct _Point { 
	double x;
	double y;
//	Point(double a, double b):x(a), y(b) {} 
} Point;

typedef struct _PointMap {
	Point point;
	int index; /* 这个成员的作用见文章后边的解释 */
#define poi_x   point.x
#define poi_y   point.y
} PointMap;

const double EPS=0.00000000001;

const double MAXDIS=9e300;

static double	Dis( PointMap po1, PointMap po2 ) /* 返回距离的平方和 */ 
{
	double xdis = po1.poi_x - po2.poi_x;
	double ydis = po1.poi_y - po2.poi_y;
	return xdis * xdis + ydis * ydis;
}

//n * n的方法,这个方法算出来的应该是标准答案
double n2MinDis( const PointMap M[], int n )
{
	//assert( n >= 1 );
	if ( n == 1 )
		return 0.0;
	int i, j;
	pair<Point, Point> pt2;
	stack<pair<Point, Point>> stk;
	double mindis = MAXDIS, tmp;
	for ( i = 0; i < n;
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值