
Objective-C实现graham scan葛立恒扫描法算法(附完整源码)
选择起始点:从所有点中选择一个凸包顶点作为起始点。 排序点:将起始点与其他所有点进行排序,根据极角(Polar Angle)从小到大排序。 构建凸包:从排序后的点中,依次检查每个点是否使得当前凸包仍为凸集。若不是,则移除不符合条件的点,并继续检查下一个点。 类定义:定义了一个 初始化方法: 排序方法: 凸包计算: 辅助方法:
发布日期:2025-04-24 00:10:15
浏览次数:3
分类:精选文章
本文共 6063 字,大约阅读时间需要 20 分钟。
Graham扫描法(Graham Scan)是一种计算平面点集凸包的有效算法。作为一名开发人员,以下是通过Objective-C实现Graham扫描法的详细说明。
Graham扫描法的基本原理
Graham扫描法的核心思想是:通过选择一个凸包中的顶点作为起点,然后依次选择向外扩展的点,构建凸包。具体步骤如下:
Objective-C实现步骤
以下是Objective-C中实现Graham扫描法的具体步骤:
#import#include @interface GrahamScan : NSObject { // 存储点的集合 NSArray *points;}// 初始化Graham扫描- (id)initWithPoints:(NSArray *)points;- (NSArray *)computeConvexHull;- (NSArray *)getPointsSortedByPolarAngle:(NSArray *)points;- (NSArray *)getPointsSortedByAngle;- (NSArray *)computeConvexHullUsingGrahamScan;@end
代码实现
#import#include @interface GrahamScan : NSObject { NSArray *points; CGPoint *pointArray; int n;}- (id)initWithPoints:(NSArray *)points;- (NSArray *)computeConvexHull;- (NSArray *)getPointsSortedByPolarAngle:(NSArray *)points;- (NSArray *)getPointsSortedByAngle;- (NSArray *)computeConvexHullUsingGrahamScan;@end@implementation GrahamScan- (id)initWithPoints:(NSArray *)points { self; self.points = points; self.n = [points count]; self.pointArray = (CGPoint *)malloc(self.n * sizeof(CGPoint)); for (int i = 0; i < self.n; i++) { self.pointArray[i] = (CGPoint){ [points[i] x, points[i] y ] }; } return self;}- (NSArray *)getPointsSortedByPolarAngle:(NSArray *)points { if (self.n < 3) return points; // 计算每个点的极角 double *theta = malloc(self.n * sizeof(double)); for (int i = 0; i < self.n; i++) { double x = self.pointArray[i].x; double y = self.pointArray[i].y; if (x == 0 && y == 0) continue; double angle = atan2(y, x); theta[i] = angle; } // 根据极角排序 for (int i = 0; i < self.n; i++) { for (int j = i + 1; j < self.n; j++) { if (theta[i] > theta[j]) { CGPoint temp = self.pointArray[i]; self.pointArray[i] = self.pointArray[j]; self.pointArray[j] = temp; double tempTheta = theta[i]; theta[i] = theta[j]; theta[j] = tempTheta; } } } // 构建结果数组 NSMutableArray *sortedPoints = [NSMutableArray array]; for (int i = 0; i < self.n; i++) { [sortedPoints addObject: self.pointArray[i]]; } return sortedPoints;}- (NSArray *)getPointsSortedByAngle { if (self.n < 3) return self.points; // 计算每个点的极角 double *theta = malloc(self.n * sizeof(double)); for (int i = 0; i < self.n; i++) { double x = self.pointArray[i].x; double y = self.pointArray[i].y; if (x == 0 && y == 0) continue; double angle = atan2(y, x); theta[i] = angle; } // 根据极角排序 for (int i = 0; i < self.n; i++) { for (int j = i + 1; j < self.n; j++) { if (theta[i] > theta[j]) { CGPoint temp = self.pointArray[i]; self.pointArray[i] = self.pointArray[j]; self.pointArray[j] = temp; double tempTheta = theta[i]; theta[i] = theta[j]; theta[j] = tempTheta; } } } NSMutableArray *sortedPoints = [NSMutableArray array]; for (int i = 0; i < self.n; i++) { [sortedPoints addObject: self.pointArray[i]]; } return sortedPoints;}- (NSArray *)computeConvexHull { if (self.n < 3) return self.points; NSArray *sortedPoints = [self getPointsSortedByPolarAngle:self.points]; NSMutableArray *hullPoints = [NSMutableArray array]; for (int i = 0; i < sortedPoints.count; i++) { bool clockwise = false; for (int j = 0; j < hullPoints.count; j++) { double crossProduct = [self crossProductBetweenPoint:sortedPoints[i] andPoint:hullPoints[j] andPoint:hullPoints[i-1]]; if (crossProduct < 0) { clockwise = true; break; } } if (clockwise) { hullPoints[0] = sortedPoints[i]; } else { hullPoints[i] = sortedPoints[i]; } } return hullPoints;}- (double)crossProductBetweenPoint:(CGPoint)point1 andPoint:(CGPoint)point2 andPoint:(CGPoint)point3 { return (point1.x - point2.x) * (point3.y - point2.y) - (point1.y - point2.y) * (point3.x - point2.x);}- (NSArray *)computeConvexHullUsingGrahamScan { if (self.n < 3) return self.points; NSArray *sortedPoints = [self getPointsSortedByPolarAngle:self.points]; NSMutableArray *hullPoints = [NSMutableArray array]; for (int i = 0; i < sortedPoints.count; i++) { bool lastClockwise = false; for (int j = 0; j < hullPoints.count; j++) { double crossProduct = [self crossProductBetweenPoint:sortedPoints[i] andPoint:hullPoints[j] andPoint:hullPoints[j-1]]; if (j == 0 || crossProduct < 0) { if (j == 0) { lastClockwise = true; } continue; } if (lastClockwise != crossProduct < 0) { hullPoints[j] = sortedPoints[i]; lastClockwise = !lastClockwise; } } } return hullPoints;}
代码解释
GrahamScan
类,用于初始化点集并计算凸包。initWithPoints
将点集转换为内部点数组,方便后续计算。getPointsSortedByPolarAngle
通过极角排序点集,getPointsSortedByAngle
则是通过极角排序点集。computeConvexHull
和computeConvexHullUsingGrahamScan
是核心方法,分别使用不同的排序方式计算凸包。crossProductBetweenPoint
用于计算向量的叉积,用于判断点的位置关系。性能优化
为了提高性能,可以尝试以下优化:
- 减少重复计算:尽量减少不必要的计算步骤,避免重复赋值。
- 使用更高效的数据结构:考虑使用数组代替动态数组,提升访问速度。
- 多线程处理:对于大规模数据集,可以尝试并行处理,减少计算时间。
以上是Graham扫描法在Objective-C中的实现与应用,希望对您有所帮助!
发表评论
最新留言
逛到本站,mark一下
[***.202.152.39]2025年03月29日 18时33分24秒
关于作者

喝酒易醉,品茶养心,人生如梦,品茶悟道,何以解忧?唯有杜康!
-- 愿君每日到此一游!