Was ist der Schnellste Weg, um finden Sie den nächsten Punkt zu einem gegebenen Punkt?
Was ist der Schnellste Weg zu finden, am nächsten Punkt der Punkt im data-array?
Angenommen ich habe ein array A
von 3D-Punkten (mit den Koordinaten x, y und z, wie üblich) und Punkt (x_p, y_p, z_p). Wie finde ich den nächsten Punkt in A
zu (x_p, y_p, z_p)?
Soweit ich weiß, ist der langsamste Weg, es zu tun, ist die Verwendung der linearen Suche. Gibt es bessere Lösungen?
Zusatz von Hilfs-Daten-Struktur ist möglich.
Du musst angemeldet sein, um einen Kommentar abzugeben.
Können Sie organisieren Sie Ihre Punkte in eine Octree. Dann brauchen Sie nur zu suchen, eine kleine Teilmenge.
Ein Octree ist eine Recht einfache Datenstruktur, die Sie implementieren können, sich selbst (das wäre eine wertvolle Erfahrung), oder Sie finden möglicherweise einige nützliche Bibliotheken, um Sie gehen.
Wenn Sie dabei eine einmalige nearest neighbour query, dann ist eine lineare Suche ist wirklich die beste, die Sie bekommen können. Dies ist natürlich vorausgesetzt, die Daten werden nicht vorab strukturiert.
Jedoch, wenn du gehst zu tun eine Menge von Abfragen gibt es ein paar Raum-Partitionierung Daten-Strukturen.Diese nehmen einige Vorverarbeitung bilden die Struktur, aber dann kann die Antwort nearest neighbour-Abfragen sehr schnell.
Da Sie den Umgang mit 3D-Raum, dem empfehle ich entweder octrees oder kd-Bäume. Kd-Bäume sind mehr Generika (Sie arbeiten für beliebige Dimensionen) und effizienter gemacht werden kann, als octrees implementiert man eine geeignete balancing-Algorithmus (z.B. median funktioniert gut), aber octrees sind einfacher zu implementieren.
ANN ist eine große Bibliothek, die mit diesen Strukturen, aber auch so für Ungefähre nächsten Nachbarn Fragen, die sind deutlich schneller, haben aber einen kleinen Fehler, Sie sind nur Näherungswerte. Wenn Sie nicht jeden Fehler, dann die Fehler gebunden zu 0.
Schlage ich vor KD-Baum wird gut funktionieren. Auch gut für die nächste Nachbar Suche.
Seinen mein Verständnis quadtree für 2d, aber man konnte berechnen, etwas für die 3d-thats ist sehr ähnlich. Dies wird Geschwindigkeit bis der Suche, aber es erfordert viel mehr Zeit zum berechnen der index-wenn on-the-fly. Ich würde vorschlagen, die Berechnung des index dann einmal zu speichern. Auf jeden lookup herausfinden, alle äußeren quads, dann arbeiten Sie Ihren Weg sucht, trifft... es würde Aussehen wie schälen einer orange. Die Geschwindigkeit wird sich erheblich vergrößern, wenn die Quadrate kleiner werden. Alles hat ein trade-off.
Ich mit einem KD-Baum zu tun, dies in O(log(n)) Zeit, vorausgesetzt, die Punkte sind zufällig verteilt, oder Sie haben einen Weg, um den Baum balanciert.
http://en.wikipedia.org/wiki/Kd-tree
KD-Bäume eignen sich hervorragend für diese Art der räumlichen Abfrage, und erlaubt auch das abrufen der nächsten k Nachbarn zu einem Abfrage-Punkt.
Es sei denn, Sie sind nicht organisiert in einer geeigneten Daten-Struktur, der einzige Weg wird sein, lineare Suche.
Ich musste das tun, etwas zu stark für die viele nächste-Nachbarn-Suche in einer Echtzeit-Umgebung, und treffen auf einen besseren Algorithmus sowohl in Bezug auf Einfachheit und Geschwindigkeit.
Nehmen Sie alle Ihre Punkte und legen Sie eine Kopie in d Listen, wobei d die Dimensionalität des Raumes. In Ihrem 3. Fall. Sortieren Sie diese drei Listen, die nach Ihrer dimension. Diese Kosten d(nlog(n)) Zeit. Und, dass es für die Datenstruktur.
Wir pflegen Sie diese richtig sortiert Listen in jeder dimension für alle Punkte in Frage. Der trick ist, dass durch die definition der Abstand in einer Richtung muss kleiner als oder gleich dem euklidischen Abstand. Also, wenn der Abstand in einer Richtung größer ist als unsere derzeitige nächsten Abstand von den nächsten bekannten Punkt, dann diesen Punkt nicht näher, und noch wichtiger, alle Punkte in diese Richtung nicht größer sein. Einmal gilt das für die 2*d-Richtungen, die wir haben, die wir per definition haben den nächsten Punkt.
Für jedes einzelne element können wir binarysearch-Methode in die sortierte Listen zu finden der nächsten position, wo der gewünschte Punkt konnte in den zwei verschiedenen Dimensionen. Mathematisch wir wissen, dass, wenn der Abstand in der +x -x +y -y (andere Abmessungen sind einfach zu addieren) Richtungen überschreitet kleinste bekannte euklidische Distanz zu einem Punkt, dass diesem Punkt muss größer sein als der Abstand, und da es ein sortiertes array, per definition, wenn wir Sie überschreiten, der Abstand in diese Richtung, wir wissen, dass wir Abbrechen können, die Richtung, da kann es keine bessere Antwort in dieser Richtung. Aber, wie wir erweitern in diese vier Richtungen können wir reduzieren unsere Wert von m, da ist es gleich der euklidische Abstand des nächsten Punktes, die wir gefunden.
Damit wir nur müssen sortierte Listen für jede Achse sortiert nach, dass die Achse. Das ist ziemlich einfach.
Dann zum Abfragen der Liste:
Wir haben sortierte Listen und müssen um den Punkt zu finden, die wir suchen, in jede Richtung, in die Liste. Wir binäre Suche, um unsere Zeit-Komplexität von log(n). Dann haben wir unsere aktuell besten Entfernung (möglicherweise unendlich) und dann bewegen wir uns in jede Richtung, die uns zur Verfügung stehen. Wie finden wir neue Punkte, aktualisieren wir den nächsten Punkt, so weit wir haben. Der trick ist, dass wir aufhören, sobald der Abstand in der jeweiligen Richtung ist weiter als unsere aktuelle bekannte nächsten Punkt.
Wenn wir also einen Punkt, bei einer bekannten am nächsten Abstand von 13 dann können wir Abbrechen Check-in die +x, -x, +y, -y, - Richtungen, sobald die Distanz in nur eine Richtung, überschreitet unsere nächsten bekannten Entfernung. Denn wenn es weiter in +x als unsere jetzige m, alle übrigen Werte von +x kann mathematisch bewiesen werden, weiter entfernt. Wie wir besser und besser nächsten Punkte, die Menge der Raum, den wir suchen müssen, wird kleiner und kleiner.
Wenn wir die Punkte in eine Richtung, die Richtung ist fertig.
Wenn der Abstand zu einem Punkt zusammen, nur dass eine dimension der Linie selbst ist größer als m, die Richtung ist fertig.
Die Lösung ist m in alle Richtungen nachgewiesen zu haben nur Punkte sein müssen, weiter als unsere beste Punkt so weit.
-- Da wir nach und nach reduzieren m, der Abstand in jeder dimension als ganzes, fällt schnell auf, das aber wie alle algorithmen, es fällt weniger schnell in höhere Dimensionen. Aber, wenn die Distanz in nur einer dimension größer ist als die besten, die wir bisher haben, muss es zwangsläufig der Fall sein, dass der ganze rest der Punkte in dieser Richtung, kann nicht besser sein.
In der Zeit Komplexität scheint auf Augenhöhe mit dem besseren. Aber in der Einfachheit der Datenstrukturen, ist dieser Algorithmus deutlich gewinnt. Es gibt eine Menge anderer Eigenschaften, die diesem Algorithmus zu einem ernsthaften Anwärter. Wenn Sie ein update von Sachen, können Sie resort die Listen mit wirklich guter Leistung, weil Sie sehr oft Sortieren bereits sortierte Listen oder fast sortierten Listen. Sie sind arrays zu iterieren. In der tatsächlichen realen Leistung die meisten Datenstrukturen saugen. In der Regel, weil der Zwischenspeicherung und wie Speicher ist gelegt, wir sollen nicht wissen über solche Dinge, aber es eine Menge Fragen. Die Daten rechts neben dem aktuellen relevanten Daten viel schneller zu den tatsächlichen Zugriff. Wenn wir schon wissen, wo der Punkt, den wir gehen, um suchen es in der Liste, die wir lösen können es sogar schneller (da würden wir nicht haben, um es zu finden mit einem binäre Suche). Und andere tricks erlaubt die Wiederverwendung der Informationen aus der vorherigen iteration hier und da. Und die zusätzlichen Dimensionen sind grundsätzlich kostenlos (außer dass dann der Wert nicht konvergieren schneller, aber das ist, weil es mehr zufällig verteilte Punkte in einem Bereich als einen Kreis mit dem gleichen radius).
Update: Mit Rücksicht auf, in den Kommentaren, die k-Punkte problem. Sie werden feststellen, dass sehr wenig geändert. Das einzig relevante an der Sache war, wenn der Punkt v ist, gefunden werden, werden weniger als die aktuelle m (findingDistanceMaxSq), dann wird dieser Punkt Hinzugefügt wird, um den heap, und der Wert für m ist gleich der euklidischen Distanz zwischen der Feststellung der position und der kth element. Die reguläre version des Algorithmus gesehen werden kann, wie in dem Fall, wo k = 1. Wir suchen für die 1-element, das wir wollen und aktualisieren Sie m, um gleich die einzige (k=1) element beim v ist gefunden zu werden, näher.
Bedenkt, dass ich immer nur Abstand comparatives in der Ferne squared form, da ich nur jemals müssen wissen, wenn es weiter Weg, und ich don ' T waste clock-Zyklen auf Quadratwurzel-Funktionen.
Und ich weiß, es ist eine perfekte Datenstruktur für die Speicherung der k-Elemente in einer Größe begrenzte heap. Offensichtlich ein array einfügen ist nicht optimal dafür. Aber, andere als zu viel java-abhängige apis, die es einfach nicht für die jeweilige Klasse, aber anscheinend ist Google Guava macht. Aber Sie nicht wirklich bemerken an alle gegeben, die Chancen stehen gut, dass Ihr k ist wahrscheinlich nicht so groß. Aber, es macht die Zeit-Komplexität für eine insertion in Punkte gespeichert in k-Zeit. Es gibt auch Dinge wie caching die Entfernung von der Suche für die Elemente.
Schließlich, und wahrscheinlich die meisten pressingly, das Projekt, das ich verwenden würde, um den code zu testen, ist im übergang, so habe ich es nicht geschafft, dieses heraus zu testen. Aber, es ist sicherlich zeigt, wie Sie dies tun: Sie speichern die k besten Ergebnisse bisher, und machen m gleich dem Abstand der der kth nächsten Punkt. -- Alles andere bleibt gleich.
Beispiel Quelle.
k
akzeptabel ist für meine AnwendungDen "Schnellsten" Weg, es zu tun, wenn man bedenkt das die Suche NUR, würde voxels. Mit einem 1:1-Punkt-voxel map, die Zugriffszeit ist konstant und wirklich schnell, nur eine Verschiebung der Koordinaten zu zentrieren Sie Ihre Punkt-Ursprung an der voxel-Herkunft(wenn nötig) und dann einfach Runde-unten die position und den Zugriff auf die voxel-array mit dem jeweiligen Wert. Für einige Fälle ist dies eine gute Wahl. So erklärte vor mir, octrees sind besser als eine 1:1 map ist nur schwer zu bekommen ist( zu viel Punkte, zu wenig voxel-Auflösung auch viel Speicherplatz).
check this out.. Sie können finden Sie CLRS computational geometry Kapitel auch..
http://www.cs.ucsb.edu/~suri/cs235/ClosestPair.pdf