Using system;
Using system. Collections. Generic;
Public class Utest
{
Static void main ()
{
Vec2 [] points = new vec2 [1, 20000];
Random random = new random (123456 );
For (INT I = 0; I <points. length; I ++)
{
Points [I] = new vec2 (random. Next (200000)/100366f, random. Next (200000)/100366f );
}
Int starttick, endtick;
Starttick = system. environment. tickcount;
Float divideconquer = (float) math. SQRT (double) mindistancesquared (points); // 140 ms
Endtick = system. environment. tickcount;
Console. writeline ("divide and conquer finishes in {} MS, result = {1}", endtick-starttick, divideconquer );
Starttick = system. environment. tickcount;
Float bruteforce = (float) math. SQRT (double) bruteforcemindistancesquared (points); // 13200 Ms
Endtick = system. environment. tickcount;
Console. writeline ("Brute Force Method finishes in {} MS, result = {1}", endtick-starttick, bruteforce );
}
Static float mindistancesquared (vec2 [] points)
{
// If the number of vertices is less than a certain number, the shortest distance is lifted directly.
If (points. length <6) return bruteforcemindistancesquared (points );
// Sort the points by the X axis. And divide it into the left part and the right part.
Array. Sort <vec2> (points, vec2.comparebyx );
Int middleidx = points. Length/2;
Vec2 [] leftpoints = new vec2 [middleidx];
Vec2 [] rightpoints = new vec2 [points. Length-middleidx];
For (INT I = 0; I <leftpoints. length; I ++)
{
Leftpoints [I] = new vec2 (points [I]. Y, points [I]. X );
}
For (INT I = 0; I <rightpoints. length; I ++)
{
Rightpoints [I] = new vec2 (points [I + middleidx]. Y, points [I + middleidx]. X );
}
// Divide and conquer: Calculate the shortest distance on the left and the shortest distance on the right.
Float L = mindistancesquared (leftpoints );
Float r = mindistancesquared (rightpoints );
Float mindistance = math. Min (L, R );
// Point close to the middle line, which may lead to a shorter distance across the middle line.
// However, the intermediate area has great limitations. Assuming that the shortest distance is S and the midline X is X, the area is limited to X-S ~ Between x + S
Float middle = points [middleidx]. X;
List <vec2> middlestrip = new list <vec2> ();
Foreach (vec2 P in points)
{
If (p. x-middle) * (p. x-middle) <mindistance) middlestrip. Add (New vec2 (P. Y, p. x ));
}
// Unlike the Wiki algorithm description, here we use the principle of separation and governance again (the code is much simpler) to calculate the shortest distance in the middle zone.
Float M = mindistancesquared (middlestrip. toarray ());
Return math. Min (mindistance, M );
}
Static float bruteforcemindistancesquared (vec2 [] points)
{
Float mindistance = float. maxvalue;
// Example, O (N * n)
For (INT I = 0; I <points. length; I ++)
{
For (Int J = I + 1; j <points. length; j ++)
{
Float distance = (points [I]-points [J]). lengthsquare ();
If (distance <mindistance) mindistance = distance;
}
}
Return mindistance;
}
}
Struct vec2
{
Public float X, Y;
Public vec2 (float X, float y)
{
This. x = x; this. Y = y;
}
Public float lengthsquare ()
{
Return x * x + y * Y;
}
Public static int comparebyx (vec2 V1, vec2 V2)
{
Return v1.x-v2.x> 0? 1: (v1.x-v2.x = 0? 0:-1 );
}
Public static vec2 operator-(vec2 V1, vec2 V2)
{
Return new vec2 (v1.x-v2.x, v1.y-v2.y );
}
}