CLOSEST-PAIR
is the problem of, given a set of distinct points
in the 2-D plane, finding the pair of points that is closest together.
The straightforward algorithm for finding the closest pair would compute the
distance for each pair of points and keep track of the minimum distance.
If there are $n$ points in the input then there are ${n \cdot (n-1) \over 2}$
pairs of points to consider, so the straightforward algorithm runs in
$\Theta(n^2)$ time.
There is a more efficient divide-and-conquer algorithm to determine the closest pair. This algorithm begins with a preprocessing step that creates two lists of the points, one sorted by x-coordinate and one sorted by y-coordinate. The recursive divide-and-conquer function then takes those two lists and
ClosestPair
that implements the $O(n \log n)$ divide-and-conquer algorithm for
CLOSEST-PAIR
. To facilitate writing your program, you
must also implement an array-based ListOfPoints
ADT as
defined by the provided header file.
Your program should read the points from standard input and write the result
to standard output. The first line of input will be an integer giving
the number of points; there will be at least two points.
The following lines of input will contain the coordinates of the points,
with one point per line and with each line containing
the x-coordinate of a point
followed by the y-coordinate, separated by whitespace (and with possibly
leading and trailing whitespace on each line); all the points
will be distinct. Each coordinate will be
a decimal floating-point value suitable for parsing by atof
with no extra characters that would prevent atof
from examining
the entire input.
The output of your program should be of the form
(9.000000, 12.000000)-(10.000000, 11.000000)=1.414214where each coordinate and the distance is output in the default form for
printf
and the first point listed is the one with the lower x-coordinate
(lower y-coordinate if the x-coordinates are the same). If there are
multiple pairs of points with the same distance then the one output
should be the first one when all such pairs are sorted in increasing order by
first x-coordinate, then first y-coordinate, then second x-coordinate,
then second y-coordinate.
If the input is not as specified then your program must behave gracefully – it must not crash or go into an infinite loop.
Your ListOfPoints
ADT must work with the provided
point
header and implementation files and must be
implemented in a file called plist.c
. The
provided point.h
, point.c
, and plist.h
(don't change them but please submit them)
and your plist.c
must be the only files needed to use your
ListOfPoints
ADT, so that the command
gcc -std=c99 -Wall -pedantic plist_unit.c plist.c point.c -lmcompiles with no warnings or errors (a sample
plist_unit.c
will be provided as part of the public tests).
Your program and any program that uses your ListOfPoints
ADT correctly must not produce any error messages when run with
valgrind --tool=memcheck --leak-check=yes -q
.
We reserve the right to deduct points from submissions for violations of the following guidelines.
#include
d regardless of what other files have
been #include
d -- if a declaration is required by
your header files, then #include
the appropriate
header file in your header file (or write a forward declaration in
your header) rather than relying on your #include
rs
to have already #include
d those header files before
they #include
yours.
const
should be declared as const
.
-Wall
and -pedantic
options.
12 2 3 2 16 3 9 6 3 7 7 9 12 10 11 15 2 15 19 16 11 17 13 19 4then the first level of the recursion splits the points into
x_left=[(2, 3), (2, 16), (3, 9), (6, 3), (7, 7), (9, 12)] x_right=[(10, 11), (15, 2), (15, 19), (16, 11), (17, 13), (19, 4)] y_left=[(2, 3), (6, 3), (7, 7), (3, 9), (9, 12), (2, 16)] y_right=[(15, 2), (19, 4), (10, 11), (16, 11), (17, 13), (15, 19)]
The recursion on the left points splits them into
x_left=[(2, 3), (2, 16), (3, 9)] x_right=[(6, 3), (7, 7), (9, 12)] y_left=[(2, 3), (3, 9), (2, 16)] y_right=[(6, 3), (7, 7), (9, 12)]where the closest pair among the left/left points is (2,3)-(3,9) and the closest pair among the right/left points is (6,3)-(7,7), which is closer. Using $x=4.5$ as the dividing line, the middle strip is the points with x-coordinates between $4.5 \pm \sqrt{17}$:
[(2, 3), (6, 3), (7, 7), (3, 9), (2, 16)]
.
The middle strip has no pair of points closer together than
(6,3)-(7,7), so that is returned as the closest pair on the left.
The recursion on the right points splits them into
x_left:[(10, 11), (15, 2), (15, 19)] x_right:[(16, 11), (17, 13), (19, 4)] y_left:[(15, 2), (10, 11), (15, 19)] y_right:[(19, 4), (16, 11), (17, 13)]where the closest pair among the left/right points is (10,11)-(15,2) and the closest pair among the right/right points is (16,11)-(17,13), which is closer. Using $x=15.5$ as the dividing line, the middle strip is the points with x-coordinates between $15.5 \pm \sqrt{5}$:
[(15, 2), (16, 11), (17, 13), (15, 19)]
. The
middle strip contains
no pair of points closer together than (16,11)-(17,3), so that
pair is returned as the closest pair on the right.
The initial call has now received (6,3)-(7,7) as the closest pair
on the left and (16,11)-(17,13) as the closest pair on the right.
(16,11)-(17,13) is the closer together of those two pairs. Using
$x=9.5$ as the dividing line, the middle strip is
the points with x-coordinates between $9.5 \pm \sqrt{5}$:
[(10, 11), (9, 12)]
. The middle strip contains the pair
(9,12)-(10,11), which is closer together than (16,11)-(17,13) and
is the closest pair out of all the original points.
/home/httpd/html/zoo/classes/cs223/f2017/Assignments/ClosestPair
: