Graham scan


Graham's scan is a method of finding the convex hull of a finite set of points in the plane with time complexity O. It is named after Ronald Graham, who published the original algorithm in 1972. The algorithm finds all vertices of the convex hull ordered along its boundary. It uses a stack to detect and remove concavities in the boundary efficiently.

Algorithm

The first step in this algorithm is to find the point with the lowest y-coordinate. If the lowest y-coordinate exists in more than one point in the set, the point with the lowest x-coordinate out of the candidates should be chosen. Call this point P. This step takes O, where n is the number of points in question.
Next, the set of points must be sorted in increasing order of the angle they and the point P make with the x-axis. Any general-purpose sorting algorithm is appropriate for this, for example heapsort.
Sorting in order of angle does not require computing the angle. It is possible to use any function of the angle which is monotonic in the interval . The cosine is easily computed using the dot product, or the slope of the line may be used. If numeric precision is at stake, the comparison function used by the sorting algorithm can use the sign of the cross product to determine relative angles.
The algorithm proceeds by considering each of the points in the sorted array in sequence. For each point, it is first determined whether traveling from the two points immediately preceding this point constitutes making a left turn or a right turn. If a right turn, the second-to-last point is not part of the convex hull, and lies 'inside' it. The same determination is then made for the set of the latest point and the two points that immediately precede the point found to have been inside the hull, and is repeated until a "left turn" set is encountered, at which point the algorithm moves on to the next point in the set of points in the sorted array minus any points that were found to be inside the hull; there is no need to consider these points again.
Again, determining whether three points constitute a "left turn" or a "right turn" does not require computing the actual angle between the two line segments, and can actually be achieved with simple arithmetic only. For three points, and, compute the z-coordinate of the cross product of the two vectors and, which is given by the expression. If the result is 0, the points are collinear; if it is positive, the three points constitute a "left turn" or counter-clockwise orientation, otherwise a "right turn" or clockwise orientation.
This process will eventually return to the point at which it started, at which point the algorithm is completed and the stack now contains the points on the convex hull in counterclockwise order.

Time complexity

Sorting the points has time complexity O.
While it may seem that the time complexity of the loop is O, because for each point it goes back to check if any of the previous points make a "right turn", it is actually O, because each point is considered at most twice in some sense.
Each point can appear only once as a point in a "left turn",
and as a point in a "right turn". The overall time complexity is therefore O, since the time to sort dominates the time to actually compute the convex hull.

Pseudocode

The code below uses a function ccw: ccw > 0 if three points make a counter-clockwise turn, clockwise if ccw < 0, and collinear if ccw = 0.
Then let the result be stored in the stack.
let points be the list of points
let stack = empty_stack
find the lowest y-coordinate and leftmost point, called P0
sort points by polar angle with P0, if several points have the same polar angle then only keep the farthest
for point in points:
# pop the last point from the stack if we turn clockwise to reach this point
while count stack > 1 and ccw, top < 0:
pop stack
push point to stack
end
Now the stack contains the convex hull, where the points are oriented counter-clockwise and P0 is the first point.
Here, next_to_top is a function for returning the item one entry below the top of stack, without changing the stack, and similarly, top for returning the topmost element.
This pseudocode is adapted from Introduction to Algorithms.

Numerical robustness

is an issue to deal with in algorithms that use finite-precision floating-point computer arithmetic. A 2004 paper analyzed a simple incremental strategy, which can be used, in particular, for an implementation of the Graham scan. The stated goal of the paper was not to specifically analyze the algorithm, but rather to provide a textbook example of what and how may fail due to floating-point computations in computational geometry. Later D. Jiang and N. F. Stewart elaborated on this and using the backward error analysis made two primary conclusions. The first is that the convex hull is a well-conditioned problem, and therefore one may expect algorithms which produce an answer within a reasonable error margin. Second, they demonstrate that a modification of Graham scan which they call Graham-Fortune does overcome the problems of finite precision and inexact data "to whatever extent it is possible to do so".