分治法求点集中的最小距离 version 0.2
来源:互联网 发布:egd网络小黄金 编辑:程序博客网 时间:2024/06/06 09:02
//// main.cpp// MinPointDistance//// Created by 孙江涛 on 13-9-29.// Copyright (c) 2013年 bryan. All rights reserved.//#include <iostream>#include <vector>#include <math.h>#include <time.h>using std::cin;using std::cout;using std::endl;using std::vector;using std::sort;struct Point{ double x; double y;};struct Result{ Point p1; Point p2; double distance;};bool sortTwoPointByX(const Point &p1,const Point &p2){ return p1.x < p2.x;}bool sortTwoPointByY(const Point &p1,const Point &p2){ return p1.y < p2.y;}void sortPointVecByX(vector<Point> &pointVec){ sort(pointVec.begin(),pointVec.end(),sortTwoPointByX);}void sortPointVecByY(vector<Point> &pointVec){ sort(pointVec.begin(),pointVec.end(),sortTwoPointByY);}void divideVector(vector<Point> &pointVec,vector<Point> &pointVec0,vector<Point> &pointVec1){ size_t size = pointVec.size(); for(vector<Point>::iterator it = pointVec.begin();it < pointVec.begin()+size/2;++it ) { Point p; p.x = (*it).x; p.y = (*it).y; pointVec0.push_back(p); } for(vector<Point>::iterator it = pointVec.begin()+size/2;it < pointVec.end();++it ) { Point p; p.x = (*it).x; p.y = (*it).y; pointVec1.push_back(p); } }double PointDistance(Point p1,Point p2){ return sqrt((p1.x-p2.x)*(p1.x-p2.x)+(p1.y-p2.y)*(p1.y-p2.y));}double MinPointDistance(double d1,double d2){ if(d1>=0&&d2>=0) {if(d1 - d2 <= 0) return d1; if(d1 - d2 >0) return d2;} if(d1>=0&&d2<0) { return d1; } if(d1<0&&d2>=0) { return d2; } return 0;}Result MinDistanceInSet(vector<Point> &pointVec){ size_t size= pointVec.size(); Result r; if(2 == size) { r.p1 = pointVec[0]; r.p2 = pointVec[1]; r.distance = PointDistance(pointVec[0],pointVec[1]); return r; } else if(3 == size) { double dis01 = PointDistance(pointVec[0], pointVec[1]); double dis12 = PointDistance(pointVec[1], pointVec[2]); double dis02 = PointDistance(pointVec[0], pointVec[2]); double dis = MinPointDistance(dis01, MinPointDistance(dis12, dis02)); if(dis-dis01 == 0) { r.p1 = pointVec[0]; r.p2 = pointVec[1]; r.distance = dis01; return r; } else if(dis-dis02 == 0) { r.p1 = pointVec[0]; r.p2 = pointVec[2]; r.distance = dis02; return r; } else if(dis-dis12 == 0) { r.p1 = pointVec[1]; r.p2 = pointVec[2]; r.distance = dis12; return r; } } else if(size>=4) { sortPointVecByX(pointVec); vector<Point> pointVec0; vector<Point> pointVec1; divideVector(pointVec, pointVec0, pointVec1); Result rPointVec0 = MinDistanceInSet(pointVec0); Result rPointVec1 = MinDistanceInSet(pointVec1); double minDistanceInTwoPart = MinPointDistance(rPointVec0.distance,rPointVec1.distance); if(minDistanceInTwoPart - rPointVec0.distance == 0) { r.distance = minDistanceInTwoPart; r.p1 = rPointVec0.p1; r.p2 = rPointVec0.p2; } else if(minDistanceInTwoPart - rPointVec1.distance == 0) { r.distance = minDistanceInTwoPart; r.p1 = rPointVec1.p1; r.p2 = rPointVec1.p2; } Point middlePoint = pointVec[size/2]; vector<Point> pointVec2; for (vector<Point>::iterator it = pointVec.begin(); it<pointVec.end(); ++it) { Point p; p.x = (*it).x; p.y = (*it).y; if(fabs(p.x-middlePoint.x) < minDistanceInTwoPart && p.x!= middlePoint.x) { pointVec2.push_back(p); } } sortPointVecByY(pointVec2); Result rPointVec2 = MinDistanceInSet(pointVec2); double minDistance = MinPointDistance(rPointVec2.distance, minDistanceInTwoPart); if(minDistance - rPointVec2.distance == 0) { r.distance = minDistance; r.p1 = rPointVec2.p1; r.p2 = rPointVec2.p2; } return r; } r.p1.x = 0; r.p1.y = 0; r.p2.x = 0; r.p2.y = 0; r.distance = -1; return r;}int main(int argc, const char * argv[]){ vector <Point> pointVec; vector <Point> pointVec0; vector <Point> pointVec1; long N = 100000; Point p; srand(time(NULL)); while((N--)>0) { double x = rand()%100000; double y = rand()%100000; p.x = x; p.y = y; pointVec.push_back(p); } clock_t t1 = clock(); Result result = MinDistanceInSet(pointVec); clock_t t2 = clock(); clock_t t = t2-t1; cout<<"最近点对的坐标为:"<<endl; cout<<"P1:( "<< result.p1.x<<","<<result.p1.y<<")"<<endl; cout<<"P2:( "<< result.p2.x<<","<<result.p2.y<<")"<<endl; cout<<"最近点对的距离为:"<<result.distance<<endl; cout<<"耗时"<<t/CLOCKS_PER_SEC<<endl; return 0;}