Priority Queue updaten nach Verringern von Schlüssel



  • Hallo,

    ich versuche mich grade daran Prim's Algorithmus mit einer Priority Queue zu implementieren;

    Dazu habe ich mir ein Struct angelegt, das die Knoten repräsentiert, so dass ich diese in der PQ ablegen kann und habe die passende comparison class angelegt:

    struct Node
    {
    	int index; //Index des Knotens
    	int weight; //Länge der kürzesten Kante die mit Spannbaum verbindet
    };
    
    class CompareNodes
    {
         public:
         bool operator()(Node& n1, Node& n2)
         {
            if (n1.weight > n2.weight) return true;
            return false;
         }
    };
    

    Im laufe des Algorithmus werden die Werte die im "weight" Feld der Knoten stehen ja immer kleiner, wenn eine neue kürzere Anbindung gefunden wird. Wie kann ich die PQ jetzt dazu anstoßen sich entsprechend neu zu sortieren?

    Laut Dokumentation benutzt die PQ von C++ einen Heap, ich könnte also auch direkt selber einen Heap verwenden. Für Heaps gibt es die Funktion make_heap, allerdings will ich nicht jedes mal den Heap komplett neu aufbauen, sondern nur das eine veränderte Element soweit im Heap aufwärts wandern lassen wie nötig.
    Oder ist die Funktion so intelligent implementiert, dass sie merkt, dass die Heap-Bedingung nur an einer Stelle verletzt ist?

    Danke im Voraus
    tela



  • Wie kann ich die PQ jetzt dazu anstoßen sich entsprechend neu zu sortieren?

    Welche PQ? Die aus der Standardbibliothek? Die kann das nicht.

    Oder ist die Funktion so intelligent implementiert, dass sie merkt, dass die Heap-Bedingung nur an einer Stelle verletzt ist?

    Bestimmt nicht.

    Aber eventuell kannst du mit den Funktionen trotzdem arbeiten. Ich bin, was Heaps angeht, nicht fit. Aber hier behauptet jemand, dass man aus Heaps in logarithmischer Zeit ein beliebiges Element entfernen kann. Du könntest also versuchen, das Element, deren Priorität du ändern willst, zu entfernen und mit einer neuen Priorität wieder einzufügen.

    Als ich mal just4fun den Dijkstra implementierte, hatte ich einfach std::set<pair<double,int>> verwendet, wobei der double-Wert dann die Priorität und der int-Wert der Knotenindex war. Diese Reihenfolge ist übrigens Absicht wegen der lexikographischen Sortierung von Paaren. Ich brauchte dann noch einen Vektor, der mir zu jedem Knotenindex auch diese Kosten speicherte, glaub'ich.

    Andere Leute haben für sowas auch schonmal multimaps verwendet.



  • Neben std::make_heap() gibts auch std::push_heap() , um ein neues Element einzufügen. Allerdings wird dabei erwartet, dass das neue Element am Ende des Arrays steht, und zuvor alle Elemente bereits in einer Heap-Struktur stehen.

    Wenn du deren Implementierung anschaust und etwas mehr über Heaps liest, sollte es nicht allzu schwer sein, eine Funktion für bestehende Elemente zu schreiben.



  • @Tela,
    das Buch ist zwar uralt, aber ich glaube, Kap. 11.2 enthält etwa das, was du suchst.
    http://www.ubreymann.de/stlb.pdf


Anmelden zum Antworten