Skip to content

Commit 324a35a

Browse files
Update GrahamScan.java (#5310)
* Update GrahamScan.java improved the Javadoc comments, clarified some methods in the Point class, and corrected some text. * Minor adjustment to GrahamScan.java * revised GrahamScan.java * Update-2 GrahamScan.java * clang format GrahamScan.java * reverted GrahamScan.java * minor updates.java * minor updates * Spc.java * clang format --------- Co-authored-by: Alex Klymenko <[email protected]>
1 parent 5fc2623 commit 324a35a

File tree

1 file changed

+49
-68
lines changed

1 file changed

+49
-68
lines changed
Original file line numberDiff line numberDiff line change
@@ -1,56 +1,56 @@
11
package com.thealgorithms.geometry;
22

3+
import java.util.ArrayList;
34
import java.util.Arrays;
45
import java.util.Comparator;
56
import java.util.Stack;
67

7-
/*
8-
* A Java program that computes the convex hull using the Graham Scan algorithm
9-
* In the best case, time complexity is O(n), while in the worst case, it is O(nlog(n)).
10-
* O(n) space complexity
8+
/**
9+
* A Java program that computes the convex hull using the Graham Scan algorithm.
10+
* The time complexity is O(n) in the best case and O(n log(n)) in the worst case.
11+
* The space complexity is O(n).
12+
* This algorithm is applicable only to integral coordinates.
1113
*
12-
* This algorithm is only applicable to integral coordinates.
13-
*
14-
* Reference:
14+
* References:
1515
* https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_algorithm.cpp
1616
* https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/geometry/graham_scan_functions.hpp
1717
* https://algs4.cs.princeton.edu/99hull/GrahamScan.java.html
1818
*/
1919
public class GrahamScan {
20+
2021
private final Stack<Point> hull = new Stack<>();
2122

2223
public GrahamScan(Point[] points) {
23-
24-
/*
25-
* pre-process the points by sorting them with respect to the bottom-most point, then we'll
26-
* push the first point in the array to be our first extreme point.
27-
*/
24+
// Pre-process points: sort by y-coordinate, then by polar order with respect to the first point
2825
Arrays.sort(points);
2926
Arrays.sort(points, 1, points.length, points[0].polarOrder());
27+
3028
hull.push(points[0]);
3129

32-
// find index of first point not equal to a[0] (indexPoint1) and the first point that's not
33-
// collinear with either (indexPoint2).
34-
int indexPoint1;
35-
for (indexPoint1 = 1; indexPoint1 < points.length; indexPoint1++) {
36-
if (!points[0].equals(points[indexPoint1])) {
30+
// Find the first point not equal to points[0] (firstNonEqualIndex)
31+
// and the first point not collinear firstNonCollinearIndex with the previous points
32+
int firstNonEqualIndex;
33+
for (firstNonEqualIndex = 1; firstNonEqualIndex < points.length; firstNonEqualIndex++) {
34+
if (!points[0].equals(points[firstNonEqualIndex])) {
3735
break;
3836
}
3937
}
40-
if (indexPoint1 == points.length) {
38+
39+
if (firstNonEqualIndex == points.length) {
4140
return;
4241
}
4342

44-
int indexPoint2;
45-
for (indexPoint2 = indexPoint1 + 1; indexPoint2 < points.length; indexPoint2++) {
46-
if (Point.orientation(points[0], points[indexPoint1], points[indexPoint2]) != 0) {
43+
int firstNonCollinearIndex;
44+
for (firstNonCollinearIndex = firstNonEqualIndex + 1; firstNonCollinearIndex < points.length; firstNonCollinearIndex++) {
45+
if (Point.orientation(points[0], points[firstNonEqualIndex], points[firstNonCollinearIndex]) != 0) {
4746
break;
4847
}
4948
}
50-
hull.push(points[indexPoint2 - 1]);
5149

52-
// Now we simply add the point to the stack based on the orientation.
53-
for (int i = indexPoint2; i < points.length; i++) {
50+
hull.push(points[firstNonCollinearIndex - 1]);
51+
52+
// Process the remaining points and update the hull
53+
for (int i = firstNonCollinearIndex; i < points.length; i++) {
5454
Point top = hull.pop();
5555
while (Point.orientation(hull.peek(), top, points[i]) <= 0) {
5656
top = hull.pop();
@@ -61,14 +61,10 @@ public GrahamScan(Point[] points) {
6161
}
6262

6363
/**
64-
* @return A stack of points representing the convex hull.
64+
* @return An iterable collection of points representing the convex hull.
6565
*/
6666
public Iterable<Point> hull() {
67-
Stack<Point> s = new Stack<>();
68-
for (Point p : hull) {
69-
s.push(p);
70-
}
71-
return s;
67+
return new ArrayList<>(hull);
7268
}
7369

7470
public record Point(int x, int y) implements Comparable<Point> {
@@ -98,80 +94,65 @@ public int y() {
9894
}
9995

10096
/**
101-
* Finds the orientation of ordered triplet.
97+
* Determines the orientation of the triplet (a, b, c).
10298
*
103-
* @param a Co-ordinates of point a <int, int>
104-
* @param b Co-ordinates of point a <int, int>
105-
* @param c Co-ordinates of point a <int, int>
106-
* @return { -1, 0, +1 } if a -→ b -→ c is a { clockwise, collinear; counterclockwise }
107-
* turn.
99+
* @param a The first point
100+
* @param b The second point
101+
* @param c The third point
102+
* @return -1 if (a, b, c) is clockwise, 0 if collinear, +1 if counterclockwise
108103
*/
109104
public static int orientation(Point a, Point b, Point c) {
110105
int val = (b.x - a.x) * (c.y - a.y) - (b.y - a.y) * (c.x - a.x);
111-
if (val == 0) {
112-
return 0;
113-
}
114-
return (val > 0) ? +1 : -1;
106+
return Integer.compare(val, 0);
115107
}
116108

117109
/**
118-
* @param p2 Co-ordinate of point to compare to.
119-
* This function will compare the points and will return a positive integer if the
120-
* point is greater than the argument point and a negative integer if the point is
121-
* less than the argument point.
110+
* Compares this point with another point.
111+
*
112+
* @param p2 The point to compare to
113+
* @return A positive integer if this point is greater, a negative integer if less, or 0 if equal
122114
*/
115+
@Override
123116
public int compareTo(Point p2) {
124-
int res = Integer.compare(this.y, p2.y);
125-
if (res == 0) {
126-
res = Integer.compare(this.x, p2.x);
127-
}
128-
return res;
117+
int cmpY = Integer.compare(this.y, p2.y);
118+
return cmpY != 0 ? cmpY : Integer.compare(this.x, p2.x);
129119
}
130120

131121
/**
132-
* A helper function that will let us sort points by their polar order
133-
* This function will compare the angle between 2 polar Co-ordinates
122+
* Returns a comparator to sort points by their polar order relative to this point.
134123
*
135-
* @return the comparator
124+
* @return A polar order comparator
136125
*/
137126
public Comparator<Point> polarOrder() {
138127
return new PolarOrder();
139128
}
140129

141130
private final class PolarOrder implements Comparator<Point> {
131+
@Override
142132
public int compare(Point p1, Point p2) {
143133
int dx1 = p1.x - x;
144134
int dy1 = p1.y - y;
145135
int dx2 = p2.x - x;
146136
int dy2 = p2.y - y;
147137

148138
if (dy1 >= 0 && dy2 < 0) {
149-
return -1; // q1 above; q2 below
139+
return -1; // p1 above p2
150140
} else if (dy2 >= 0 && dy1 < 0) {
151-
return +1; // q1 below; q2 above
152-
} else if (dy1 == 0 && dy2 == 0) { // 3-collinear and horizontal
153-
if (dx1 >= 0 && dx2 < 0) {
154-
return -1;
155-
} else if (dx2 >= 0 && dx1 < 0) {
156-
return +1;
157-
} else {
158-
return 0;
159-
}
141+
return 1; // p1 below p2
142+
} else if (dy1 == 0 && dy2 == 0) { // Collinear and horizontal
143+
return Integer.compare(dx2, dx1);
160144
} else {
161-
return -orientation(Point.this, p1, p2); // both above or below
145+
return -orientation(Point.this, p1, p2); // Compare orientation
162146
}
163147
}
164148
}
165149

166150
/**
167-
* Override of the toString method, necessary to compute the difference
168-
* between the expected result and the derived result
169-
*
170-
* @return a string representation of any given 2D point in the format (x, y)
151+
* @return A string representation of this point in the format (x, y)
171152
*/
172153
@Override
173154
public String toString() {
174-
return "(" + x + ", " + y + ")";
155+
return String.format("(%d, %d)", x, y);
175156
}
176157
}
177158
}

0 commit comments

Comments
 (0)