Objective-C实现graham scan葛立恒扫描法算法(附完整源码)
发布日期:2025-04-24 00:10:15 浏览次数:3 分类:精选文章

本文共 6063 字,大约阅读时间需要 20 分钟。

Graham扫描法(Graham Scan)是一种计算平面点集凸包的有效算法。作为一名开发人员,以下是通过Objective-C实现Graham扫描法的详细说明。

Graham扫描法的基本原理

Graham扫描法的核心思想是:通过选择一个凸包中的顶点作为起点,然后依次选择向外扩展的点,构建凸包。具体步骤如下:

  • 选择起始点:从所有点中选择一个凸包顶点作为起始点。
  • 排序点:将起始点与其他所有点进行排序,根据极角(Polar Angle)从小到大排序。
  • 构建凸包:从排序后的点中,依次检查每个点是否使得当前凸包仍为凸集。若不是,则移除不符合条件的点,并继续检查下一个点。
  • 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则是通过极角排序点集。
  • 凸包计算computeConvexHullcomputeConvexHullUsingGrahamScan是核心方法,分别使用不同的排序方式计算凸包。
  • 辅助方法crossProductBetweenPoint用于计算向量的叉积,用于判断点的位置关系。
  • 性能优化

    为了提高性能,可以尝试以下优化:

    • 减少重复计算:尽量减少不必要的计算步骤,避免重复赋值。
    • 使用更高效的数据结构:考虑使用数组代替动态数组,提升访问速度。
    • 多线程处理:对于大规模数据集,可以尝试并行处理,减少计算时间。

    以上是Graham扫描法在Objective-C中的实现与应用,希望对您有所帮助!

    上一篇:Objective-C实现graph list图列算法(附完整源码)
    下一篇:Objective-C实现gradient descent准梯度下降法算法(附完整源码)

    发表评论

    最新留言

    逛到本站,mark一下
    [***.202.152.39]2025年03月29日 18时33分24秒

    关于作者

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

    推荐文章