E ExamMaster

CS Core & Software Engineering · Data Structures & Algorithms

Convex Hull

The smallest convex polygon containing a point set: Graham scan (polar sort plus left-turn stack), the CCW test, and the divide-and-conquer merge by common tangents.

Five concepts on convex hull — the smallest convex polygon, the CCW left-turn test, Graham's polar sort plus stack, the divide-and-conquer tangent merge, and O(n \log n) versus Jarvis O(nh). Running example: A(0,0), B(1,0), C(2,1), D(1,1) interior, E(1,2), F(0,1).

  • CS Core & Software Engineering
  • Hard level
  • 5 concepts

1Smallest convex polygon containing the points

A set S of points in the plane is convex if every segment between two points of S stays inside S. The convex hull of a finite point set P is the smallest convex set that contains P — a convex polygon whose vertices are a subset of P. Every other point of P lies inside or on that polygon.

The hull is the object. Graham scan and divide-and-conquer are two ways to name its vertices. Interior points are not a second object; they are the points the algorithms discard.

Figure. Hull A-B-C-E-F in counterclockwise order. D is interior (terracotta) and is not a hull vertex. Positions are schematic, not a millimetre plot.

What belongs on the hull

  1. ExtremeA vertex of the hull is a point of P that is a corner of the taut rubber-band.
  2. InteriorA point strictly inside that polygon is not a hull vertex.
  3. Collinear edgePoints in the middle of a hull edge may be kept or dropped by policy; they are not interior.

Six points, one interior

P = {A(0,0), B(1,0), C(2,1), D(1,1), E(1,2), F(0,1)}. Which point is strictly interior to the hull polygon A-B-C-E-F?

  • hull vertices (CCW from A)A, B, C, E, F
  • D(1,1) versus polygon A-B-C-E-Fstrictly inside
  • points on the hull5 of 6

Pro tip. D sits at the average of B and E and of several other pairs. It is the point Graham will pop.

The convex hull of a finite point set in the plane is
  1. The smallest convex polygon that contains every point
  2. The axis-aligned bounding box of the points
  3. The complete graph on the points

The bounding box is convex but not smallest (it can add empty corners). The complete graph is not a polygon.

2Left turn from a cross product

Walking p \to q \to r, the signed area of triangle pqr is \mathrm{CCW}(p,q,r) = (q_x-p_x)(r_y-p_y) - (q_y-p_y)(r_x-p_x). Positive means a left turn at q (counterclockwise). Negative means a right turn. Zero means p,q,r are collinear.

Graham's stack pops while the last three points make a non-left turn, so the surviving chain is always a left-turning (convex) chain. The test is two multiplies and a subtract — not an angle in degrees.

Figure. Walk C(2,1) → D(1,1) → E(1,2). The cross product (−1)·1 − 0·(−1) is −1, a right turn at D, so Graham pops D. Positive CCW would have kept D.

Evaluate one turn

  1. Two edgesVectors q-p and r-p (or r-q; the sign convention must stay consistent).
  2. Cross(q_x-p_x)(r_y-p_y)-(q_y-p_y)(r_x-p_x).
  3. SignPositive: keep q. Negative: q is a right-turn dent, pop it.

The turn that pops D

On the running set, after the stack is [A, B, C, D] the next point is E(1,2). Is C-D-E a left turn?

  • C=(2,1), D=(1,1), E=(1,2)walk C → D → E
  • D-C = (-1,0), E-C = (-1,1)using p=C, q=D, r=E
  • (-1)\cdot 1 - 0\cdot(-1)-1 — right turn, pop D

Pro tip. The same three points with E first would flip the sign. Always walk the current stack order, oldest to newest.

CCW(p,q,r) < 0 means
  1. A right turn at q, so Graham pops q
  2. A left turn at q, so Graham keeps q
  3. The three points form a triangle of area 1

Negative is clockwise / right turn. Area is |\mathrm{CCW}|/2, not the sign, and is not fixed at 1.

3Graham scan: polar sort, then a stack

Graham scan names the hull vertices in order. Choose the lowest point (leftmost on a tie) as the origin p_0. Sort the remaining points by polar angle around p_0 (break ties by distance). Then walk that order with a stack: push the next point; while the last three points on the stack are not a left turn, pop the middle one.

The sort is O(n \log n). The walk is O(n) because each point is pushed once and popped at most once. That is why Graham is O(n \log n), not O(n^2).

Six labelled points A through F. A hull chain grows A-B-C-D. E is offered; D is marked as a right-turn dent and fades; the surviving chain is A-B-C-E-F enclosing D.
Graham walk on the running six. C-D-E is a right turn, so D is popped; the hull pentagon is A-B-C-E-F.

One Graham pass

  1. OriginLowest y, then leftmost x.
  2. SortPolar angle about the origin; CCW from the +x direction.
  3. ScanPush; pop while CCW of the top three is \le 0.

Graham scan

def ccw(p, q, r):
    return (q[0] - p[0]) * (r[1] - p[1]) - (q[1] - p[1]) * (r[0] - p[0])

def graham(points):
    p0 = min(points, key=lambda p: (p[1], p[0]))
    rest = [p for p in points if p != p0]
    rest.sort(key=lambda p: (math.atan2(p[1] - p0[1], p[0] - p0[0]),
                             (p[0] - p0[0]) ** 2 + (p[1] - p0[1]) ** 2))
    stack = [p0]
    for p in rest:
        while len(stack) >= 2 and ccw(stack[-2], stack[-1], p) <= 0:
            stack.pop()
        stack.append(p)
    return stack

Full scan on the running six

Origin A, polar order B, C, D, E, F. Record the stack after each next point is considered.

  • start + B, then C (left)[A, B, C]
  • D (left at C-D)[A, B, C, D]
  • E: C-D-E right, pop D; B-C-E left[A, B, C, E]
  • F (left)[A, B, C, E, F]

Pro tip. The polar order put D between C and E. The stack, not the sort, is what proved D interior.

Coding lab. Graham scan on six points runs in the app, with checks on your output.

Graham scan is O(n \log n) because
  1. The polar sort is O(n \log n) and the stack walk is O(n)
  2. Each of n points is compared with all others
  3. The CCW test is O(n)

One CCW test is O(1). Nested all-pairs comparison is Jarvis-shaped, not Graham.

4Divide-and-conquer: hull halves, then tangents

The divide-and-conquer hull sorts the points by x-coordinate, recursively computes the hull of the left half and of the right half, and merges those two convex polygons. The merge finds the upper common tangent and the lower common tangent — the two bridges that touch each hull once — and drops every vertex that lies strictly between the two contact points on the inner sides.

Finding the two tangents is O(n) on already-convex chains (walk the chains until both bridges are supporting lines). So T(n) = 2T(n/2) + O(n) = O(n \log n) after the initial sort — the same class as Graham, a different split.

Figure. Upper tangent (0,2)-(3,2) and lower tangent (0,0)-(3,0). The terracotta mid points sit on the inner chains and are dropped. Schematic, not to scale.

One merge

  1. SplitMedian x. Recurse on left and right.
  2. TangentsUpper and lower common supporting lines of the two hulls.
  3. Drop inner chainsVertices between the two contact points on each hull are interior to the merge.

Two triangles become a box

Left hull (0,0)-(1,1)-(0,2). Right hull (3,0)-(2,1)-(3,2). What are the common tangents, and which vertices disappear?

  • lower tangent(0,0) — (3,0)
  • upper tangent(0,2) — (3,2)
  • inner vertices (1,1) and (2,1)dropped — inside the rectangle
  • merged hull(0,0), (3,0), (3,2), (0,2)

Pro tip. Each half-hull was correct. The merge is what proved the two mid-edge points interior to the union.

The D&C hull merge drops a vertex when
  1. It lies on a chain between the two common-tangent contact points
  2. Its polar angle about the lowest point is not unique
  3. The two halves have different sizes

Polar angle is Graham's sort key, not the D&C merge. Unequal halves are fine. The tangents name the bridges; everything between them on the inner sides is interior.

5O(n log n), or O(n h) when h is tiny

Graham and D&C hull are both O(n \log n). Gift wrapping (Jarvis march) starts at an extreme point and, at each hull vertex, scans all remaining points to find the next one with the smallest polar step — O(n) work per hull edge, so O(nh) for h hull vertices.

Jarvis wins only when h is much smaller than \log n is large — a hull that is a triangle on a million interior points. In the worst case h = n (points already in convex position) and Jarvis is O(n^2). A comparison-based hull is \Omega(n \log n) because sorting reduces to it (lift numbers onto a convex curve).

No new point set — the three-row time table is the comparison.

Hull algorithms
AlgorithmTimeWhen
Graham scanO(n \log n)Default
D&C + tangentsO(n \log n)Same class; syllabus D&C extra
Jarvis marchO(nh)Tiny h; worst case O(n^2)

h = 3 versus h = n

n = 16 points. Compare Jarvis against Graham when the hull is a triangle (h = 3) and when all 16 points are on the hull.

  • Jarvis, h=3: O(nh)16 \times 3 = 48 scans of a point
  • Jarvis, h=1616 \times 16 = 256
  • Graham (either case)O(16 \log 16) = O(64)

Pro tip. The 48 versus 64 is why Jarvis is quoted for tiny hulls. The 256 is why it is not the default.

Jarvis march is O(n^2) when
  1. Every point is a hull vertex, so h=n
  2. The polar sort fails
  3. The set has an interior point

Time is O(nh). Interior points make h smaller, which helps Jarvis. There is no polar sort in Jarvis.

Notes

  • The convex hull of a finite point set in the plane is the smallest convex polygon that contains every point — equivalently, the intersection of all convex sets that contain the points, or the vertices you would hit with a taut rubber band.
  • Graham scan: pick the lowest (then leftmost) point as origin, sort the others by polar angle, then scan with a stack, popping while the last three points make a right turn.
  • The orientation test (cross product) decides left versus right turn: (q_x-p_x)(r_y-p_y)-(q_y-p_y)(r_x-p_x)>0 is a left turn at q walking p \to q \to r.
  • Divide-and-conquer hull: sort by x, hull the left and right halves, then replace the two polygons by the polygon formed from their upper and lower common tangents.
  • Graham and the D&C merge are both O(n \log n). Gift wrapping (Jarvis) is O(nh) for h hull vertices — better only when h is tiny.

Formulas

  • CCW(p,q,r) = (q_x-p_x)(r_y-p_y) - (q_y-p_y)(r_x-p_x). Positive = left turn.
  • Graham scan: O(n \log n) for the polar sort, O(n) for the stack scan.
  • D&C hull: T(n)=2T(n/2)+O(n)=O(n \log n) after an O(n \log n) x-sort.
  • Jarvis march: O(nh) for h hull vertices.
  • Any comparison-based hull is \Omega(n \log n) in the worst case (reduction from sorting).

Exam traps & shortcuts

  • Interior points fail a left-turn test on the scan and are popped. Do not test 'inside the final polygon' as a first step — the scan is the test.
  • Collinear points make CCW = 0. Decide a policy (keep the farthest, or keep all) and apply it consistently; the running example has no three on a line.
  • Graham's O(n \log n) is the sort. The stack walk is linear because each point is pushed and popped at most once.
  • D&C hull is the syllabus divide-and-conquer extra. It is not a faster class than Graham — both are O(n \log n).

Reference tables

Polar order B, C, D, E, F about A. D is the only pop.

Running Graham stack
Next pointTurn testedStack after
CA-B-C leftA B C
DB-C-D leftA B C D
EC-D-E right, pop DA B C E
FC-E-F leftA B C E F

D&C hull is the syllabus extra, not a faster bound.

Two algorithms, one class
MethodSplitCombine
GrahamPolar sort about lowest pointLinear stack of left turns
D&CMedian xUpper and lower common tangents

Recap

Night-before hull pegs.

Object
Smallest convex polygon containing the points. Interior points are discarded.
CCW
(q_x-p_x)(r_y-p_y)-(q_y-p_y)(r_x-p_x)>0 is a left turn.
Graham
Lowest point, polar sort, pop right turns. O(n \log n).
D&C
Hull left, hull right, two tangents. Also O(n \log n).
Jarvis
O(nh). Quadratic when h=n.

Practise Convex Hull

Reading is free and needs no account. Practice, mocks and progress live in the app.

  • A 5-question practice set that ends the chapter
  • 5 quick checks with worked explanations
  • Timed mocks scored with the real marking scheme
  • Readiness tracked per topic, kept on your device
Continue with Google — freeNo card, no trial. Works offline once installed.