现在的位置: 首页 > 综合 > 正文

Graham算法——凸包问题

2014年03月07日 ⁄ 综合 ⁄ 共 2287字 ⁄ 字号 评论关闭

Graham算法的思路,大概如下:对平面上的点的集合,从中找到有最小的y坐标值的点p,然后根据其它点和p的连线与正x轴所成的角度将平面上的点进行排序,排序后,扫描从p开始的有序列表,如果所有的这些点都在凸包上,那么每三个相继的点,会组成一个左旋,从另一方面说,如果相继的三个点,p1,p2,p3,组成了一个右旋,则可以立即去除p2,因为它不可能在凸包上!如此扫描到p3等于p时,扫描就结束,剩下的点,就全都是凸包上的点了!

这里面有几个难点:

1、如何根据他们的夹角,来对双链表进行排序

2、如何判断左右旋

3、如何扫描

针对第一个问题,在下面的程序中,采用的是简单的选择排序,即每次在无序区内找到最大的元素,将其放到有序区内,因为这是对双链表进行排序,就有双链表的排序特点,但我认为采用插入,即断开结点之间的联系始终不是好的办法,所以采用了这种简单的交换的方法,虽然效率慢了点,但是重在说明问题!

针对第二个问题,判断左右旋,其实可以用一个行列式的值来判定

|x1   x2  x3|

|y2   y2  y3|

|1    1     1 |

若该行列式为正,则为左旋,反之,则为右旋。其实这个行列式是根据点是在直线的上方还是下方而推断出来的,用直线方程也可以判断左右旋。

针对第三个问题看下面的代码中的scan()函数就很清楚了!

 

下面是用c++写的具体代码:

 

抱歉!评论已关闭.