Skip to content

Commit 77259b7

Browse files
authored
Merge pull request TheAlgorithms#502 from MarisaAfuera/master
Refactorized ClosestPair.java in order to be compliant with java sun rules
2 parents 65a919f + 88f8155 commit 77259b7

File tree

1 file changed

+348
-0
lines changed

1 file changed

+348
-0
lines changed

divideconquer/ClosestPair.java

+348
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,348 @@
1+
package divideconquer;
2+
3+
/**
4+
5+
* For a set of points in a coordinates system (10000 maximum),
6+
* ClosestPair class calculates the two closest points.
7+
8+
* @author: anonymous
9+
* @author: Marisa Afuera
10+
*/
11+
12+
public final class ClosestPair {
13+
14+
15+
/** Number of points */
16+
int numberPoints = 0;
17+
/** Input data, maximum 10000. */
18+
private Location[] array;
19+
/** Minimum point coordinate. */
20+
Location point1 = null;
21+
/** Minimum point coordinate. */
22+
Location point2 = null;
23+
/** Minimum point length. */
24+
private static double minNum = Double.MAX_VALUE;
25+
/** secondCount */
26+
private static int secondCount = 0;
27+
28+
/**
29+
* Constructor.
30+
*/
31+
ClosestPair(int points) {
32+
numberPoints = points;
33+
array = new Location[numberPoints];
34+
}
35+
36+
/**
37+
Location class is an auxiliary type to keep points coordinates.
38+
*/
39+
40+
public static class Location {
41+
42+
double x = 0;
43+
double y = 0;
44+
45+
/**
46+
* @param xpar (IN Parameter) x coordinate <br/>
47+
* @param ypar (IN Parameter) y coordinate <br/>
48+
*/
49+
50+
Location(final double xpar, final double ypar) { //Save x, y coordinates
51+
this.x = xpar;
52+
this.y = ypar;
53+
}
54+
55+
}
56+
57+
public Location[] createLocation(int numberValues) {
58+
return new Location[numberValues];
59+
60+
}
61+
62+
public Location buildLocation(double x, double y){
63+
return new Location(x,y);
64+
}
65+
66+
67+
/** xPartition function: arrange x-axis.
68+
* @param a (IN Parameter) array of points <br/>
69+
* @param first (IN Parameter) first point <br/>
70+
* @param last (IN Parameter) last point <br/>
71+
* @return pivot index
72+
*/
73+
74+
public int xPartition(
75+
final Location[] a, final int first, final int last) {
76+
77+
Location pivot = a[last]; // pivot
78+
int pIndex = last;
79+
int i = first - 1;
80+
Location temp; // Temporarily store value for position transformation
81+
for (int j = first; j <= last - 1; j++) {
82+
if (a[j].x <= pivot.x) { // Less than or less than pivot
83+
i++;
84+
temp = a[i]; // array[i] <-> array[j]
85+
a[i] = a[j];
86+
a[j] = temp;
87+
}
88+
}
89+
i++;
90+
temp = a[i]; // array[pivot] <-> array[i]
91+
a[i] = a[pIndex];
92+
a[pIndex] = temp;
93+
return i; // pivot index
94+
}
95+
96+
/** yPartition function: arrange y-axis.
97+
* @param a (IN Parameter) array of points <br/>
98+
* @param first (IN Parameter) first point <br/>
99+
* @param last (IN Parameter) last point <br/>
100+
* @return pivot index
101+
*/
102+
103+
public int yPartition(
104+
final Location[] a, final int first, final int last) {
105+
106+
Location pivot = a[last]; // pivot
107+
int pIndex = last;
108+
int i = first - 1;
109+
Location temp; // Temporarily store value for position transformation
110+
for (int j = first; j <= last - 1; j++) {
111+
if (a[j].y <= pivot.y) { // Less than or less than pivot
112+
i++;
113+
temp = a[i]; // array[i] <-> array[j]
114+
a[i] = a[j];
115+
a[j] = temp;
116+
}
117+
}
118+
i++;
119+
temp = a[i]; // array[pivot] <-> array[i]
120+
a[i] = a[pIndex];
121+
a[pIndex] = temp;
122+
return i; // pivot index
123+
}
124+
125+
/** xQuickSort function: //x-axis Quick Sorting.
126+
* @param a (IN Parameter) array of points <br/>
127+
* @param first (IN Parameter) first point <br/>
128+
* @param last (IN Parameter) last point <br/>
129+
*/
130+
131+
public void xQuickSort(
132+
final Location[] a, final int first, final int last) {
133+
134+
if (first < last) {
135+
int q = xPartition(a, first, last); // pivot
136+
xQuickSort(a, first, q - 1); // Left
137+
xQuickSort(a, q + 1, last); // Right
138+
}
139+
}
140+
141+
/** yQuickSort function: //y-axis Quick Sorting.
142+
* @param a (IN Parameter) array of points <br/>
143+
* @param first (IN Parameter) first point <br/>
144+
* @param last (IN Parameter) last point <br/>
145+
*/
146+
147+
public void yQuickSort(
148+
final Location[] a, final int first, final int last) {
149+
150+
if (first < last) {
151+
int q = yPartition(a, first, last); // pivot
152+
yQuickSort(a, first, q - 1); // Left
153+
yQuickSort(a, q + 1, last); // Right
154+
}
155+
}
156+
157+
/** closestPair function: find closest pair.
158+
* @param a (IN Parameter) array stored before divide <br/>
159+
* @param indexNum (IN Parameter) number coordinates divideArray <br/>
160+
* @return minimum distance <br/>
161+
*/
162+
163+
public double closestPair(final Location[] a, final int indexNum) {
164+
165+
Location[] divideArray = new Location[indexNum];
166+
System.arraycopy(a, 0, divideArray, 0, indexNum); // Copy previous array
167+
int totalNum = indexNum; // number of coordinates in the divideArray
168+
int divideX = indexNum / 2; // Intermediate value for divide
169+
Location[] leftArray = new Location[divideX]; //divide - left array
170+
//divide-right array
171+
Location[] rightArray = new Location[totalNum - divideX];
172+
if (indexNum <= 3) { // If the number of coordinates is 3 or less
173+
return bruteForce(divideArray);
174+
}
175+
//divide-left array
176+
System.arraycopy(divideArray, 0, leftArray, 0, divideX);
177+
//divide-right array
178+
System.arraycopy(
179+
divideArray, divideX, rightArray, 0, totalNum - divideX);
180+
181+
double minLeftArea = 0; //Minimum length of left array
182+
double minRightArea = 0; //Minimum length of right array
183+
double minValue = 0; //Minimum lengt
184+
185+
minLeftArea = closestPair(leftArray, divideX); // recursive closestPair
186+
minRightArea = closestPair(rightArray, totalNum - divideX);
187+
// window size (= minimum length)
188+
minValue = Math.min(minLeftArea, minRightArea);
189+
190+
// Create window. Set the size for creating a window
191+
// and creating a new array for the coordinates in the window
192+
for (int i = 0; i < totalNum; i++) {
193+
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
194+
if (xGap < minValue) {
195+
secondCount++; // size of the array
196+
} else {
197+
if (divideArray[i].x > divideArray[divideX].x) {
198+
break;
199+
}
200+
}
201+
}
202+
// new array for coordinates in window
203+
Location[] firstWindow = new Location[secondCount];
204+
int k = 0;
205+
for (int i = 0; i < totalNum; i++) {
206+
double xGap = Math.abs(divideArray[divideX].x - divideArray[i].x);
207+
if (xGap < minValue) { // if it's inside a window
208+
firstWindow[k] = divideArray[i]; // put in an array
209+
k++;
210+
} else {
211+
if (divideArray[i].x > divideArray[divideX].x) {
212+
break;
213+
}
214+
}
215+
}
216+
yQuickSort(firstWindow, 0, secondCount - 1); // Sort by y coordinates
217+
/* Coordinates in Window */
218+
double length = 0;
219+
// size comparison within window
220+
for (int i = 0; i < secondCount - 1; i++) {
221+
for (int j = (i + 1); j < secondCount; j++) {
222+
double xGap = Math.abs(firstWindow[i].x - firstWindow[j].x);
223+
double yGap = Math.abs(firstWindow[i].y - firstWindow[j].y);
224+
if (yGap < minValue) {
225+
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
226+
// If measured distance is less than current min distance
227+
if (length < minValue) {
228+
// Change minimum distance to current distance
229+
minValue = length;
230+
// Conditional for registering final coordinate
231+
if (length < minNum) {
232+
minNum = length;
233+
point1 = firstWindow[i];
234+
point2 = firstWindow[j];
235+
}
236+
}
237+
}
238+
else {
239+
break;
240+
}
241+
}
242+
}
243+
secondCount = 0;
244+
return minValue;
245+
}
246+
247+
/** bruteForce function: When the number of coordinates is less than 3.
248+
* @param arrayParam (IN Parameter) array stored before divide <br/>
249+
* @return <br/>
250+
*/
251+
252+
public double bruteForce(final Location[] arrayParam) {
253+
254+
double minValue = Double.MAX_VALUE; // minimum distance
255+
double length = 0;
256+
double xGap = 0; // Difference between x coordinates
257+
double yGap = 0; // Difference between y coordinates
258+
double result = 0;
259+
260+
if (arrayParam.length == 2) {
261+
// Difference between x coordinates
262+
xGap = (arrayParam[0].x - arrayParam[1].x);
263+
// Difference between y coordinates
264+
yGap = (arrayParam[0].y - arrayParam[1].y);
265+
// distance between coordinates
266+
length = Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
267+
// Conditional statement for registering final coordinate
268+
if (length < minNum) {
269+
minNum = length;
270+
271+
}
272+
point1 = arrayParam[0];
273+
point2 = arrayParam[1];
274+
result = length;
275+
}
276+
if (arrayParam.length == 3) {
277+
for (int i = 0; i < arrayParam.length - 1; i++) {
278+
for (int j = (i + 1); j < arrayParam.length; j++) {
279+
// Difference between x coordinates
280+
xGap = (arrayParam[i].x - arrayParam[j].x);
281+
// Difference between y coordinates
282+
yGap = (arrayParam[i].y - arrayParam[j].y);
283+
// distance between coordinates
284+
length =
285+
Math.sqrt(Math.pow(xGap, 2) + Math.pow(yGap, 2));
286+
// If measured distance is less than current min distance
287+
if (length < minValue) {
288+
// Change minimum distance to current distance
289+
minValue = length;
290+
if (length < minNum) {
291+
// Registering final coordinate
292+
minNum = length;
293+
point1 = arrayParam[i];
294+
point2 = arrayParam[j];
295+
}
296+
}
297+
}
298+
}
299+
result = minValue;
300+
301+
}
302+
return result; // If only one point returns 0.
303+
}
304+
305+
/** main function: execute class.
306+
* @param args (IN Parameter) <br/>
307+
* @throws IOException If an input or output
308+
* exception occurred
309+
*/
310+
311+
public static void main(final String[] args) {
312+
313+
//Input data consists of one x-coordinate and one y-coordinate
314+
315+
ClosestPair cp = new ClosestPair(12);
316+
cp.array[0]=cp.buildLocation(2,3);
317+
cp.array[1]=cp.buildLocation(2,16);
318+
cp.array[2]=cp.buildLocation(3,9);
319+
cp.array[3]=cp.buildLocation(6,3);
320+
cp.array[4]=cp.buildLocation(7,7);
321+
cp.array[5]=cp.buildLocation(19,4);
322+
cp.array[6]=cp.buildLocation(10,11);
323+
cp.array[7]=cp.buildLocation(15,2);
324+
cp.array[8]=cp.buildLocation(15,19);
325+
cp.array[9]=cp.buildLocation(16,11);
326+
cp.array[10]=cp.buildLocation(17,13);
327+
cp.array[11]=cp.buildLocation(9,12);
328+
329+
System.out.println("Input data");
330+
System.out.println("Number of points: "+ cp.array.length);
331+
for (int i=0;i<cp.array.length;i++){
332+
System.out.println("x: " + cp.array[i].x + ", y: " + cp.array[i].y);
333+
}
334+
335+
cp.xQuickSort(cp.array, 0, cp.array.length-1); // Sorting by x value
336+
337+
double result; // minimum distance
338+
339+
result = cp.closestPair(cp.array, cp.array.length);
340+
// ClosestPair start
341+
// minimum distance coordinates and distance output
342+
System.out.println("Output Data");
343+
System.out.println("(" + cp.point1.x + ", " + cp.point1.y + ")");
344+
System.out.println("(" + cp.point2.x + ", " + cp.point2.y + ")");
345+
System.out.println("Minimum Distance : " + result);
346+
347+
}
348+
}

0 commit comments

Comments
 (0)