Effiziente abfragbare Datenstruktur zur Darstellung eines Bildschirms mit Fenstern

7

(Dies hängt mit meiner anderen Frage zusammen, siehe hier )

Stellen Sie sich einen Bildschirm mit 3 Fenstern vor:

Geben Sie hier die Bildbeschreibung ein

Ich möchte eine effiziente Datenstruktur finden, um dies darzustellen und gleichzeitig diese Aktionen zu unterstützen:

  • Gibt eine Liste von Koordinaten zurück, in denen ein bestimmtes Fenster positioniert werden kann, ohne sich mit anderen zu überschneiden
    • Wenn wir im obigen Beispiel ein Fenster der Größe 2x2 einfügen möchten, sind die möglichen Positionen (8, 6), (8, 7), ..
  • Ändern der Größe eines Fensters auf dem Bildschirm, ohne andere Fenster zu überlappen, während das Seitenverhältnis beibehalten wird
  • Fenster an Position x, y einfügen (vorausgesetzt, es überlappt sich nicht)

Im Moment besteht mein naiver Ansatz darin, eine Reihe von Fenstern beizubehalten, alle Punkte auf dem Bildschirm zu überprüfen und zu überprüfen, ob sich eines in einem der Fenster befindet. Dies ist wobei die Breite, Höhe des Bildschirms und die Anzahl der Fenster darin sind. Beachten Sie, dass im Allgemeinen klein ist (z. B. <10), wenn jedes Fenster viel Platz beansprucht.O(nmw)n,mww

daniel.jackson
quelle
Aus Neugier, warum Sie müssen die Menge der Punkte? Wenn es darum geht, ein anderes Problem zu lösen, gibt es möglicherweise einen grundlegend besseren Ansatz. Wenn es keine Fenster gibt, ist es dann nicht immer noch , um die Lösung zu konstruieren, dh alle Punkte im roten Rechteck? Wie möchten Sie die Punktmenge darstellen? O(nm)
Patrick87
@ Patrick87: Du hast Recht, und vielleicht gehe ich das in die falsche Richtung. Ich werde die Frage bearbeiten.
daniel.jackson

Antworten:

3

Eine einfache Optimierung des naiven Algorithmus besteht darin, einige Punkte zu überspringen, wenn Sie einen Punkt überprüfen, der von einem Fenster abgedeckt wird. Angenommen, Sie scannen von links nach rechts und von oben nach unten. Wenn Sie im Fenster auf ein stoßen , können Sie von nach springen und fortfahren. Wenn die Fenster groß sind und sich nicht überlappen, würde ich wild vermuten, dass Sie einen -Algorithmus erhalten, wobei die Anzahl der Punkte in der Menge ist, die Sie zurückgeben.(x,y)w=(l,r,w,h)xl+w+1O(p)p

In der Tat könnte es vorteilhaft sein zu sehen, ob die Fenster im Allgemeinen breiter oder höher sind. Bei hohen Fenstern ist es besser, von oben nach unten und von links nach rechts zu scannen. Bei großen Fenstern sollte sich die oben beschriebene Methode durchsetzen. Möglicherweise können Sie die Idee aufgreifen und diagonal scannen / überspringen, um eine ausgewogene Leistung auf ganzer Linie zu erzielen.

Wenn Sie von links nach rechts und von oben nach unten scannen, können Sie sich für nachfolgende Zeilen (Werte von ) daran erinnern, dass Sie denselben Wert auf denselben Wert überspringen müssen , wenn Sie erreichen das (möglicherweise nicht, wenn sich ein anderes Fenster überlappt). Dies würde das Scannen von oben nach unten, von links nach rechts und diagonal unnötig machen, um eine gleichwertige Leistung zu erzielen.hyxl+w+1x

Im Allgemeinen haben Sie jetzt zwei Datenstrukturen: eine mit Vorverarbeitungs- / Konstruktionsaufwand und -Suchen und eine mit (möglicherweise; vielleicht können Sie es besser machen, oder meine Optimierung tut es nicht wirklich erreichen) Vorverarbeitung / Konstruktion und möglicherweise (Hash / Nachschlagetabelle) oder (BST). Es gibt also bereits zwei Alternativen, die beide ziemlich gut sind, wirklich ...O(1)O(w)O(p)O(1)O(logp)

Patrick87
quelle
Wie würden Sie das erreichen, was Sie im dritten Absatz beschrieben haben? Im Moment habe ich Ihren ersten Vorschlag umgesetzt, indem ich alle Fenster durchgegangen bin. Wenn es eine Überlappung gibt, überspringe ich das Fenster. Dies wird in einer Schleife ausgeführt, bis sich die (x, y) -Koordinate des aktuellen Fensters, das ich anpassen möchte, nicht in einer einzigen Iteration ändert.
daniel.jackson
Führen Sie möglicherweise eine Hash-Tabelle mit (y-Zähler, links, rechts) Tripeln, wobei das mittlere Element den Hash bestimmt. füge eins hinzu und initialisiere mit (y + h, x - 1, l + w + 1), wenn du ein Rechteck triffst; Überprüfen Sie die Tabelle, bevor Sie Rechtecke durchsuchen. wenn y> y_max, ignorieren und entfernen; so etwas vielleicht.
Patrick87