Sorting a point array efficiently in C?
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.
Introduction
Sorting arrays of 2D points is a routine operation in computational geometry, computer graphics, and spatial indexing. C's standard library provides qsort, which accepts a custom comparator, making it straightforward to sort by any criterion. This article shows how to define a Point struct and write comparators for x-coordinate, y-coordinate, Euclidean distance, and angular (polar) ordering.
Defining the Point Struct
Start with a simple struct that holds the x and y coordinates. Using double keeps the implementation general enough for both integer and floating-point data.
All comparator functions in the following sections follow the signature required by qsort: they take two const void * arguments and return a negative, zero, or positive integer.
Sorting by X-Coordinate
The most common ordering sorts points left to right. When two points share the same x value, break ties by y.
Avoid the shortcut return (int)(pa->x - pb->x) because casting a small floating-point difference to int truncates values between -1 and 1 to zero, producing incorrect results for closely spaced points.
Sorting by Y-Coordinate
Sorting top-to-bottom (or bottom-to-top) follows the same pattern with x and y swapped.
This ordering is useful in sweep-line algorithms that process events from bottom to top across the plane.
Sorting by Distance from the Origin
Sorting by Euclidean distance is needed for nearest-neighbor queries and radial partitioning. Since sqrt is monotonic, you can compare squared distances to avoid the expensive square-root call.
To sort by distance from an arbitrary reference point instead of the origin, pass the reference through a file-scope variable or wrap the comparator in a closure-like pattern using a helper struct.
Angular (Polar) Sorting
Angular sorting arranges points by their angle relative to a reference point, measured counterclockwise from the positive x-axis. This is a core step in algorithms like Graham scan for convex hulls.
atan2 returns values in the range [-pi, pi]. If you need all-positive angles (0 to 2*pi), add 2 * M_PI to negative results before comparing. When the reference point is not the origin, subtract its coordinates from each point before computing the angle.
Putting It All Together
Here is a complete example that sorts the same array four different ways.
Compile with gcc -O2 -lm points.c -o points. The -lm flag links the math library for atan2 and sqrt.
Performance Considerations
qsort uses an optimized comparison-based sort internally, typically introsort or merge sort depending on the C library. Its average and worst-case complexity is O(n log n). For extremely large point sets (millions of elements), consider these further optimizations:
- Use
qsort_r(POSIX) or a wrapper to pass extra context (like a reference point) to comparators without relying on global variables. - Pre-compute derived values (squared distance, angle) into a parallel array and sort an index array to avoid recomputing inside the comparator.
- For distance-based sorting, skip
sqrtentirely by comparing squared distances.
Common Pitfalls
- Subtracting doubles and casting to int. The expression
(int)(pa->x - pb->x)silently truncates fractional differences to zero, making the sort non-deterministic for closely spaced points. - Forgetting the tie-breaker. A comparator that returns 0 for distinct points with equal primary keys produces an unstable order, which breaks algorithms that depend on a total ordering.
- Calling atan2 with both arguments zero.
atan2(0, 0)is implementation-defined; filter out the origin before angular sorting if it can appear in the data. - Modifying the array during sorting. The comparator must never write to the elements it receives;
qsortassumes the comparator is a pure function. - Ignoring NaN coordinates. Any comparison involving NaN returns false, which violates the strict weak ordering that
qsortrequires and can cause infinite loops or crashes.
Summary
- Represent 2D points as a struct with
double xanddouble y, and useqsortwith custom comparators. - Sort by x-coordinate or y-coordinate using explicit less-than/greater-than checks instead of subtraction casts.
- Compare squared distances rather than actual distances to avoid unnecessary
sqrtcalls. - Use
atan2for angular sorting and handle the [-pi, pi] range and origin edge cases. - Pre-compute derived values for large datasets to avoid redundant work inside the comparator.
Related reading
- Sorting a Python list by two fields
- Sorting a queue using same queue
- Sorting a sequence by swapping adjacent elements using minimum swaps
- Sorting a set of values
- Sorting algorithm of Arrays in Java.util package
- Sorting algorithm to keep equal values separated
- Sorting an array in C?
- Sorting zipped locked containers in C using boost or the STL

DSA Fundamentals
Master algorithmic patterns and data structures through hands-on LeetCode-style problems - from arrays and hashing to dynamic programming and advanced graphs.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Data Structures & Algorithms practice on Codemia
Step through 300 algorithm problems with animated visualisers that show the data structure changing as the code runs.