zoukankan      html  css  js  c++  java
  • 《算法》BEYOND 部分程序 part 3

    ▶ 书中第六章部分程序,加上自己补充的代码,包括 Graham 扫描生成凸包,计算最远点对

    ● Graham 扫描生成凸包

     1 package package01;
     2 
     3 import java.util.Arrays;
     4 import edu.princeton.cs.algs4.StdIn;
     5 import edu.princeton.cs.algs4.StdOut;
     6 import edu.princeton.cs.algs4.Point2D;
     7 import edu.princeton.cs.algs4.Stack;
     8 
     9 public class class01
    10 {
    11     private Stack<Point2D> hull = new Stack<Point2D>();
    12 
    13     public class01(Point2D[] points)
    14     {
    15         if (points == null || points.length == 0)
    16             throw new IllegalArgumentException("argument is null");
    17         int n = points.length;
    18         Point2D[] a = new Point2D[n];
    19         for (int i = 0; i < n; i++)
    20             a[i] = points[i];
    21 
    22         Arrays.sort(a);                             // Y 坐标升序排序,等值的按 X 坐标升序排序,保证 a[0] 为最下最左,a[1] 为
    23         Arrays.sort(a, 1, n, a[0].polarOrder());    // 以 a[0] 为原点,幅角升序排序
    24         hull.push(a[0]);                            // 第一个点
    25         int k1;                                     // 找到下一个相异点
    26         for (k1 = 1; k1 < n; k1++)
    27         {
    28             if (!a[0].equals(a[k1]))
    29                 break;
    30         }
    31         if (k1 == n)
    32             return;
    33         int k2;                                     // 找到下一个非共线点
    34         for (k2 = k1 + 1; k2 < n; k2++)
    35         {
    36             if (Point2D.ccw(a[0], a[k1], a[k2]) != 0)
    37                 break;
    38         }
    39         hull.push(a[k2 - 1]);                       // a[k2-1] 是与 a[0],a[k1] 共线的最后一个点(也可以先压 a[k1] 然后跳过 a[k2-1])
    40         for (int i = k2; i < n; i++)
    41         {
    42             Point2D top = hull.pop();
    43             for (; Point2D.ccw(hull.peek(), top, a[i]) <= 0; top = hull.pop()); // 倒数第 2 点、倒数第 1 点和当前点计算三角形面积,逆时针方向为正
    44                                                                                 // 吐栈吐到这 3 点的面积为正为止,压入倒数第 2 点当前点
    45             hull.push(top);
    46             hull.push(a[i]);
    47         }
    48         assert isConvex();
    49     }
    50 
    51     public Iterable<Point2D> hull()                 // 得到凸包的迭代器
    52     {
    53         Stack<Point2D> s = new Stack<Point2D>();
    54         for (Point2D p : hull)
    55             s.push(p);
    56         return s;
    57     }
    58 
    59     private boolean isConvex()                      // 检查凸性
    60     {
    61         int n = hull.size();
    62         if (n <= 2) return true;
    63 
    64         Point2D[] points = new Point2D[n];
    65         int k = 0;
    66         for (Point2D p : hull())
    67             points[k++] = p;
    68 
    69         for (int i = 0; i < n; i++)
    70         {
    71             if (Point2D.ccw(points[i], points[(i + 1) % n], points[(i + 2) % n]) <= 0)
    72                 return false;
    73         }
    74         return true;
    75     }
    76 
    77     public static void main(String[] args)
    78     {
    79         int n = StdIn.readInt();
    80         Point2D[] points = new Point2D[n];
    81         for (int i = 0; i < n; i++)
    82         {
    83             int x = StdIn.readInt(), y = StdIn.readInt();
    84             points[i] = new Point2D(x, y);
    85         }
    86         class01 graham = new class01(points);
    87         for (Point2D p : graham.hull())
    88             StdOut.println(p);
    89     }
    90 }

    ● 计算最远点对

     1 package package01;
     2 
     3 import edu.princeton.cs.algs4.StdIn;
     4 import edu.princeton.cs.algs4.StdOut;
     5 import edu.princeton.cs.algs4.Point2D;
     6 import edu.princeton.cs.algs4.GrahamScan;
     7 
     8 public class class01
     9 {
    10     private Point2D best1, best2;
    11     private double bestDistanceSquared = Double.NEGATIVE_INFINITY;  // 当前最远点对距离的平方
    12 
    13     public class01(Point2D[] points)
    14     {
    15         if (points == null || points.length <= 1)
    16             throw new IllegalArgumentException("constructor argument is null");
    17 
    18         GrahamScan graham = new GrahamScan(points);
    19 
    20         int m = 0;// 凸包点数
    21         for (Point2D p : graham.hull())
    22             m++;
    23         Point2D[] hull = new Point2D[m + 1];                        // 凸包顶点放入 a[1] ~ a[m]
    24         m = 1;
    25         for (Point2D p : graham.hull())
    26             hull[m++] = p;
    27         m--;                                                        // m 等于凸包顶点数
    28 
    29         if (m == 1) // 所有点都相同
    30             return;
    31         if (m == 2) // 所有点共线
    32         {
    33             best1 = hull[1];
    34             best2 = hull[2];
    35             bestDistanceSquared = best1.distanceSquaredTo(best2);
    36             return;
    37         }
    38 
    39         int k = 2;
    40         for (; Point2D.area2(hull[m], hull[1], hull[k + 1]) > Point2D.area2(hull[m], hull[1], hull[k]); k++);   // a[k] 是距离直线 a[1]a[m] 最远的点
    41 
    42         int j = k;
    43         for (int i = 1; i <= k && j <= m; i++)                      // j 搜索后半部分,i 搜索前半部分
    44         {
    45             update(hull[i], hull[j]);                               // i 挪动一位,检查 a[i] 和 a[j] 距离是否更大
    46             for (j++; (j <= m) && Point2D.area2(hull[i], hull[i + 1], hull[j]) > Point2D.area2(hull[i], hull[i + 1], hull[j - 1]); j++) 
    47                                                                     // j 挪动保持 a[j] 远离直线 a[i]a[i+1]
    48                 update(hull[i], hull[j]);
    49         }
    50     }
    51 
    52     private void update(Point2D x, Point2D y)
    53     {
    54         double distanceSquared = x.distanceSquaredTo(y);            
    55         if (distanceSquared > bestDistanceSquared)
    56         {
    57             best1 = x;
    58             best2 = y;
    59             bestDistanceSquared = distanceSquared;
    60         }
    61     }
    62 
    63     public Point2D either()
    64     {
    65         return best1;
    66     }
    67 
    68     public Point2D other()
    69     {
    70         return best2;
    71     }
    72 
    73     public double distance()
    74     {
    75         return Math.sqrt(bestDistanceSquared);
    76     }
    77 
    78     public static void main(String[] args)
    79     {
    80         int n = StdIn.readInt();
    81         Point2D[] points = new Point2D[n];
    82         for (int i = 0; i < n; i++)
    83         {
    84             int x = StdIn.readInt(), y = StdIn.readInt();
    85             points[i] = new Point2D(x, y);
    86         }
    87         class01 farthest = new class01(points);
    88         StdOut.println(farthest.distance() + " from " + farthest.either() + " to " + farthest.other());
    89     }
    90 }
  • 相关阅读:
    JavaScript定时器及相关面试题
    单线程JavaScript
    webpack基础入门
    SQL Server 服务器器信息备份(二)--权限备份
    SQL Server 服务器器信息备份(一)--login新建脚本备份
    Raid与DAN、SAN、NAS基础
    AlwaysOn可用性组功能测试(三)--其他测试
    AlwaysOn可用性组功能测试(二)--SQL Server群集故障转移对AlwaysOn可用性组的影响
    AlwaysOn可用性组功能测试(一)--AlwaysOn故障转移测试
    AlwaysOn可用性组测试环境安装与配置(一)--SQL群集环境搭建
  • 原文地址:https://www.cnblogs.com/cuancuancuanhao/p/10115990.html
Copyright © 2011-2022 走看看