Mergen von 2 Max Heaps

Mariexshhx

Bekanntes Mitglied
Ist es irgendie möglich 2 Max heaps in O(log n) zu mergen? normal hat insert ja eine Laufzeit von O(logn). wenn ich jetzt aber n Element aus dem einem heap in den anderen einfüge habe ich ja O(n*logn)?
 

LimDul

Top Contributor

KonradN

Super-Moderator
Mitarbeiter

Mariexshhx

Bekanntes Mitglied
Das dürfte aber falsch sein. O(n log n) ist nicht O(n).


Da kann man den Unterschied auch sehr schön in einer Grtafik sehen.
ich dachte vielleicht liegt es an der Anzahl der Knoten in den zwei Bäumen, weil ein Baum ist vollständig und der andere nicht. Der gemerge Baum hat ja nie eine größere Höhe als der Baum mit 2^m Knoten. Und das es aus diesem Grund in log n funktioniert. Jedoch muss man ja für jedes Element heapify aufrufen also wiederrum n*log n

wichtig nochmal zu sagen meine beiden Max heaps sind nicht als Array gespeichert sondern als Binärbaum
 

Mariexshhx

Bekanntes Mitglied
ich dachte vielleicht liegt es an der Anzahl der Knoten in den zwei Bäumen, weil ein Baum ist vollständig und der andere nicht. Der gemerge Baum hat ja nie eine größere Höhe als der Baum mit 2^m Knoten. Und das es aus diesem Grund in log n funktioniert. Jedoch muss man ja für jedes Element heapify aufrufen also wiederrum n*log n

wichtig nochmal zu sagen meine beiden Max heaps sind nicht als Array gespeichert sondern als Binärbaum
also die Elemente des Baums mit 2^m -1 Knoten passt genau in die letze Ebene des Baums mit 2^m jedoch sind dann möglicherweise die max heap Eigenschaften verletzt
 

weihnachtspyramide

Aktives Mitglied
Mein Verdacht erhärtet sich:

1670490488939.png


addAll iteriert ebenfalls über jedes Element.

Das dürfte aber falsch sein. O(n log n) ist nicht O(n).
Da hast du recht.

Aber der Wikipedia-Eintrag schließt O(n log n) nicht aus...

Edit:

Java:
 553:   /**
 554:    * Copies all elements of the given map into this TreeMap.  If this map
 555:    * already has a mapping for a key, the new mapping replaces the current
 556:    * one.
 557:    *
 558:    * @param m the map to be added
 559:    * @throws ClassCastException if a key in m is not comparable with keys
 560:    *         in the map
 561:    * @throws NullPointerException if a key in m is null, and the comparator
 562:    *         does not tolerate nulls
 563:    */
 564:   public void putAll(Map<? extends K, ? extends V> m)
 565:   {
 566:     Iterator itr = m.entrySet().iterator();
 567:     int pos = m.size();
 568:     while (--pos >= 0)
 569:       {
 570:         Map.Entry<K,V> e = (Map.Entry<K,V>) itr.next();
 571:         put(e.getKey(), e.getValue());
 572:       }
 573:   }


Zumindest in Java ist es so, dass O(n * log n) benötigt wird. Bin mir nicht sicher, ob der Wikipedia-Eintrag richtig ist.
 
Zuletzt bearbeitet:

LimDul

Top Contributor
Man muss jetzt aufpassen - Komplexititätstheorie ist alles, aber nicht trivial.

Nur weil eine TreeMap einen Neuaufbau in O(n log(n)) macht, sagt das erst mal null darüber aus ob ein Merge von Max Heaps nicht trotzdem in O(log n) geht. Wie man ja verlinkt sieht, es bei Binomial Heaps.

Dann kommt noch ein weiteres Problem hinzu - die O-Notation ist ein asymptotische Laufzeitbeschreibung.

So ist in der O-Notation O(n log(n)) besser als O(n). Aber wenn die Faktoren wie folgt sind:

0.00001 *n*log(n) vs. 5.000.000 * n ist in der Praxis für alle relevanten n der O(n log(n)) Algorithmus besser.

Das nächste Problem ist dann bei Datenstrukturen, die mehrere Operationen anbieten - da ist je nach konkreter Datenstruktur immer ein Tradeoff. Reduziere ich die Laufzeit bei der einen Operation erhöhe ich sie bei der anderen.
 

Mariexshhx

Bekanntes Mitglied
Man muss jetzt aufpassen - Komplexititätstheorie ist alles, aber nicht trivial.

Nur weil eine TreeMap einen Neuaufbau in O(n log(n)) macht, sagt das erst mal null darüber aus ob ein Merge von Max Heaps nicht trotzdem in O(log n) geht. Wie man ja verlinkt sieht, es bei Binomial Heaps.

Dann kommt noch ein weiteres Problem hinzu - die O-Notation ist ein asymptotische Laufzeitbeschreibung.

So ist in der O-Notation O(n log(n)) besser als O(n). Aber wenn die Faktoren wie folgt sind:

0.00001 *n*log(n) vs. 5.000.000 * n ist in der Praxis für alle relevanten n der O(n log(n)) Algorithmus besser.

Das nächste Problem ist dann bei Datenstrukturen, die mehrere Operationen anbieten - da ist je nach konkreter Datenstruktur immer ein Tradeoff. Reduziere ich die Laufzeit bei der einen Operation erhöhe ich sie bei der anderen.
aber ein max Heap ist doch kein binominal Heap?
 

weihnachtspyramide

Aktives Mitglied
Bezüglich der Komplexität: Nehmen wir mal an, der tatsächliche Aufwand für einen optimalen Merge-Algorithmus würde 10*n betragen, was schon eine optimistische Schätzung ist. Also pro Element werden nicht mehr als 10 Elementaroperationen für das Einfügen benötigt. Dann würde sich der optimale Algorithmus erst ab 22.000 Elementen "lohnen", also ab dieser Anzahl geringfügig schneller werden:


Ich danke, das könnte mit ein Grund sein, weshalb man in Java einen Algorithmus gewählt hat, der jedes Element einzeln hinzufügt.

BTW: Der Probealarm funktionierte bei mir gerade. :D
 

weihnachtspyramide

Aktives Mitglied
wichtig nochmal zu sagen meine beiden Max heaps sind nicht als Array gespeichert sondern als Binärbaum
Gehen wir das mal theoretisch durch:

Angenommen, es gibt n Elemente in Halde A und m Elemente in Halde B. Halde B soll in Halde A eingefügt werden. Weiterhin gelte: (A) Alle Elemente in Halde B sind kleiner als das kleinste Element in Halde A - oder (B) alle Elemente in Halde B sind größer als das größte Element in Halde A.

Für (A) und (B) gilt: Ich vergrößere Halde A um m Elemente. Danach kann ich alle Elemente aus Halde B in O(1) einfügen. Der Aufwand wäre also konstant.

Gilt (A) oder (B) jedoch nicht, so komme ich zumindest nicht umhin, alle Elemente aus Halde B einzeln durchzugehen, und damit in O(m*log(n+m)) einzufügen ... was in etwa O(n) entsprechen sollte (hoffe ich).

Weshalb log(n+m)? Die initiale n-elementige Halde A wächst ja um m Elemente an... Ich benötige also log(n) + log(n+1) + log(n+2) + ... + log(n+m) Operationen, um alle m Elemente einzufügen.

Siehe auch: https://en.wikipedia.org/wiki/Heap_(data_structure)#Comparison_of_theoretic_bounds_for_variants

Deshalb ist die Eingangsfrage, glaube ich, nicht möglich.
 

Ähnliche Java Themen

Neue Themen


Oben