用分治法解决平面集问题就是把问题分割成更小的子问题,
运用递归的思想来对小问题求解,最后得到原问题的答案
用java实现中遇到的问题:
Q:寻找距离直线最远的点,从哪些点内寻找
A:先对所有的点进行排序,可能的最远点的集合就为x落在线段之间内的点
Q:递归的结束条件
A:当找到的点到直线的最远距离为0时,递归就可以结束了
代码有一点点问题,如果三个点在一条直线上且都为凸包的端点,则只会输出两个端点。此问题可以通过改变递归的终止条件来解决。
java代码(仅供参考,数据集很小,只有十个点):
package Code.src.algorithm;
import java.util.*;
class Point{
int x;
int y;
public Point(int x, int y){
this.x = x;
this.y = y;
}
}
public class GraphTheory_TuPackage {
public static void main(String[] args){
ArrayList<Point> PointArr = new ArrayList<Point>();
PointArr.add(new Point(0,-1));PointArr.add(new Point(1,1));PointArr.add(new Point(2,2));PointArr.add(new Point(3,1));
PointArr.add(new Point(4,2));PointArr.add(new Point(1,-3));PointArr.add(new Point(3,-1));PointArr.add(new Point(4,-2));
PointArr.add(new Point(5,-1));PointArr.add(new Point(4,-4));PointArr.add(new Point(0,0));
// ArrayListPrintf(PointArr);
//重写排序方法,按x从小到大排序
Collections.sort(PointArr, new Comparator<Point>() {
@Override
public int compare(Point o1, Point o2) {
if (o1.x < o2.x)
return -1;
if (o1.x > o2.x)
return 1;
return 0;
}
});
// ArrayListPrintf(PointArr);
int left = 0; int right = PointArr.size()-1;
ArrayList<Point> Duandian = new ArrayList<Point>();
//x方向上的两个极值点加入数组
Duandian.add(PointArr.get(left));Duandian.add(PointArr.get(right));
//寻找上包部分的端点
findUpPoint(left, right, PointArr, Duandian);
//寻找下包部分的端点
findDownPoint(left, right, PointArr, Duandian);
ArrayListPrintf(Duandian);
}
//寻找凸包上半部分的端点
public static void findUpPoint(int left, int right, ArrayList<Point> PointArr, ArrayList<Point> Duandian){
int distance = Integer.MIN_VALUE;
int best = 0;
Point pointLeft = PointArr.get(left);
Point pointRight = PointArr.get(right);
//x在left和right之间的点为目标点,进行遍历
for (int i=left; i<=right; i++){
Point pointNow = PointArr.get(i);
int distance_now = get_distance(pointLeft, pointRight, pointNow);
//找到距离直线最远的点
if (distance_now > distance){
distance = distance_now;
best = i;
}
}
//如果没有目标点(或者目标点就在线段上),递归结束
if (distance != 0){
Duandian.add(PointArr.get(best));
findUpPoint(left, best, PointArr, Duandian);
findUpPoint(best, right, PointArr, Duandian);
}
}
//寻找凸包下半部分的端点
public static void findDownPoint(int left, int right, ArrayList<Point> PointArr, ArrayList<Point> Duandian){
int distance = Integer.MAX_VALUE;
int best = 0;
Point leftPoint = PointArr.get(left);
Point rightPoint = PointArr.get(right);
for (int i=left; i<=right; i++){
Point pointNow = PointArr.get(i);
int distance_now = get_distance(leftPoint, rightPoint, pointNow);
if (distance_now < distance){
distance = distance_now;
best = i;
}
}
if (distance != 0){
Duandian.add(PointArr.get(best));
findDownPoint(left, best, PointArr, Duandian);
findDownPoint(best, right, PointArr, Duandian);
}
}
//c点到直线ab的距离公式
public static int get_distance(Point a, Point b, Point c){
return (a.x*b.y+b.x*c.y+c.x*a.y)-(a.x*c.y+b.x*a.y+c.x*b.y);
}
public static void ArrayListPrintf(ArrayList<Point> a){
for (int i=0;i<a.size();i++)
System.out.print(a.get(i).x+" "+a.get(i).y+"; ");
System.out.println();
}
}