c++ 凸包 分治算法_【算法】凸包问题--分治法

凸包问题--分治法求能够完全包含平面上n个给定点的凸多边形。示例:一、分治法:(一)算法思路:(这里所说的直线都是有向直线的。)将数组升序排序,若x轴坐标相同,按照y轴坐标升序排序。最左边的点p1和最右边的点p_n一定是该集合凸包的顶点。该直线将点分为两个集合,上包为S1,下包为S2。在p1 p_n线上的点不可能是凸包的顶点,所以不用考虑。在上包S1中,找到p_max(距离直线p1p_n最远距离的...
摘要由CSDN通过智能技术生成

凸包问题--分治法

求能够完全包含平面上n个给定点的凸多边形。

示例:

一、分治法:

(一)算法思路:

(这里所说的直线都是有向直线的。)

将数组升序排序,若x轴坐标相同,按照y轴坐标升序排序。

最左边的点p1和最右边的点p_n一定是该集合凸包的顶点。该直线将点分为两个集合,上包为S1,下包为S2。在p1 p_n线上的点不可能是凸包的顶点,所以不用考虑。

在上包S1中,找到p_max(距离直线p1p_n最远距离的点),若有两个距离同样远的点,取∠p_max p1 p_n最大的那个点(即△p_max p1 p_n面积最大)。

(一次递归到这里结束)

找出S1中所有在直线p1 p_max左边的点,这些点中一定有构成上包中左半部分边界的顶点,用上面的算法递归查找点,直到上包就是以p1和p_n为端点的线段。

下包S2中找下边界 同理。

*如何判断点是否在直线p1 p_max左边(同 p1 p_n上方)?

如果q1(x1,y1),q2(x2,y2),q3(x3,y3)是平面上的任意三个点,那么三角形△q1 q2 q3的面积等于下面这个行列式绝对值的二分之一。

当且仅当点q3=(x3,y3)位于直线q1 q2的左侧时,该表达式的符号为正,该点位于两个点确定的直线的左侧。

(二)实现中碰到的问题

如何用快速排序来排序Point类(内有坐标x,y)的一维数组?

按照x坐标排序很简单,若碰到x相同,y不同的怎么办?

在快排的原基础上修改,以j向前逼近说明:

(第一个while循环)当前比较数的横坐标>基准点的时,j向前逼近。此处不加等于号,排序是不稳定的,即相等元素的相对位置可能发生改变。

(第二个while为添加内容)比较相等元素的纵坐标,基准点的更小,j继续向前逼近,即相等元素的相对位置不发生改变;否则,则改变。也就是将原来快排中while循环拆分为两个,增加相等元素另外比较纵坐标的情况。

while (i < j && points[j].getX() > center.getX()) {

j--;

}

while (i < j && center.getX() == points[j].getX() && points[j].getY() > center.getY()) {

j--;

}

/*

* (i

* points[j].getX()且points[j].getY()

*/

if (i < j)// 跳出循环也有可能时因为i=j,所以这里要判断一下

points[i++] = points[j];

如果使用全局数组visit标识点是否访问,能确定凸包的所有顶点,但怎么顺序输出?

在已经求的凸包顶点里逐一确定边界,判断是不是所有点都在这条边界的一侧,如果是则确定一条边界。

convexHullList.add(convexHullVertex[0]);// 开始点

int haveCount = 1;// 已经加入点的个数

// 逐条确定边界,判断是否除了该条假设边界上的点,其他凸包的顶点都在直线的右边。

// 如果是,则此条直线为边界;如果不是,取下一个边界终点,继续判断。

int start = 0;// 起点

for (int end = start + 1; haveCount < count;) {

boolean boundRight = true;

for (int i = 0; i < count; i++) {

while (i < count && (i == start || i == end)) {// 不能写if,start和end可能是连在一起的

i++;

}

if (i >= count)

break;

// 点在直线左侧或线上,错误

if (PointJudge(convexHullVertex[start], convexHullVertex[end], convexHullVertex[i]) >= 0) {

boundRight = false;

end = (end + 1) % count;// end取下一个

break;

}

}

if (boundRight == true) {

convexHullList.add(convexHullVertex[end]);

start = end;

end = (start + 1) % count;

haveCount++;

}

}

(三)注意点

注意方法PointJudge(Point beginP, Point endP,Point p)和PointCal(Point beginP,Point endP,Point p)中,传参放在第几个:

前两个点是直线的两端,第三个是需要判断的点

注意下包循环中的 起始点、终点、判断条件

for (i

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值