<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
	<id>https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Bottom-Up-Heapsort</id>
	<title>Bottom-Up-Heapsort - Versionsgeschichte</title>
	<link rel="self" type="application/atom+xml" href="https://wiki-de.moshellshocker.dns64.de/index.php?action=history&amp;feed=atom&amp;title=Bottom-Up-Heapsort"/>
	<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Bottom-Up-Heapsort&amp;action=history"/>
	<updated>2026-05-29T23:52:11Z</updated>
	<subtitle>Versionsgeschichte dieser Seite in Wikipedia (Deutsch) – Lokale Kopie</subtitle>
	<generator>MediaWiki 1.43.8</generator>
	<entry>
		<id>https://wiki-de.moshellshocker.dns64.de/index.php?title=Bottom-Up-Heapsort&amp;diff=121669&amp;oldid=prev</id>
		<title>imported&gt;Leyo: Layout</title>
		<link rel="alternate" type="text/html" href="https://wiki-de.moshellshocker.dns64.de/index.php?title=Bottom-Up-Heapsort&amp;diff=121669&amp;oldid=prev"/>
		<updated>2025-04-16T21:46:23Z</updated>

		<summary type="html">&lt;p&gt;Layout&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Neue Seite&lt;/b&gt;&lt;/p&gt;&lt;div&gt;&amp;#039;&amp;#039;&amp;#039;BottomUp-Heapsort&amp;#039;&amp;#039;&amp;#039;  ist ein [[Sortierverfahren|Sortieralgorithmus]], der u.&amp;amp;nbsp;a. [[1990]] von [[Ingo Wegener]] vorgestellt wurde und im Durchschnitt besser als [[Quicksort]] arbeitet,&lt;br /&gt;
falls man Vergleichsoperationen hinreichend stark gewichtet. Es ist eine Variante von [[Heapsort]], die vor allem zur Sortierung sehr großer Datenmengen geeignet ist, wenn (im Vergleich zu den notwendigen Vertauschungsoperationen) ein relativ hoher Aufwand pro Vergleichsoperation erforderlich ist.&lt;br /&gt;
&lt;br /&gt;
Diese Variante wurde allerdings bereits [[1986]] von Svante Carlsson analysiert,&lt;br /&gt;
der letztlich eine weitere Variante fand, die sogar eine [[Zeitkomplexität|worst-case]]-Laufzeit von nur &amp;#039;&amp;#039;n&amp;#039;&amp;#039; log &amp;#039;&amp;#039;n&amp;#039;&amp;#039; + O(&amp;#039;&amp;#039;n &amp;#039;&amp;#039; log log &amp;#039;&amp;#039;n&amp;#039;&amp;#039;) Vergleichen hat. Entdeckt wurde dieser Bottom-Up-Heapsort bereits von [[Robert Floyd|Robert W Floyd]] (bei einer Überarbeitung des ursprünglichen&lt;br /&gt;
Heapsorts von Williams), der aber das Laufzeitverhalten dieser Variante nicht beweisen konnte.&lt;br /&gt;
&lt;br /&gt;
Er benötigt zum Sortieren einer Folge von n Schlüsseln&lt;br /&gt;
im schlechtesten Fall nur 1,5 &amp;#039;&amp;#039;n&amp;#039;&amp;#039; log &amp;#039;&amp;#039;n&amp;#039;&amp;#039; + 2&amp;#039;&amp;#039;n&amp;#039;&amp;#039; Schlüsselvergleiche.&lt;br /&gt;
Im Durchschnittsfall benötigt BottomUp-Heapsort nur &amp;#039;&amp;#039;n&amp;#039;&amp;#039; log &amp;#039;&amp;#039;n&amp;#039;&amp;#039; + O(&amp;#039;&amp;#039;n&amp;#039;&amp;#039;) Schlüsselvergleiche.&lt;br /&gt;
&lt;br /&gt;
== Prinzip der Sortierung ==&lt;br /&gt;
&lt;br /&gt;
Beim Sortieren mit normalem Heapsort finden beim Absenken eines Elements zwei Vergleiche pro Ebene statt:&lt;br /&gt;
&lt;br /&gt;
# Welcher der beiden Nachfolgeknoten des abzusenkenden Elements ist größer?&lt;br /&gt;
# Ist der nun bestimmte Nachfolgeknoten größer als das abzusenkende Element?&lt;br /&gt;
&lt;br /&gt;
Nachdem ein [[Binärbaum]] zur Hälfte aus [[Blatt (Graphentheorie)|Blättern]] besteht und zudem beim Sortieren ehemalige Blätter mit ohnehin schon eher niedrigen Werten abgesenkt werden, ist es wahrscheinlich, dass ein Element bis zur Blattebene oder in deren Nähe abgesenkt werden muss. Deshalb kann es lohnend sein, auf den zweiten Vergleich zu verzichten und auf Verdacht bis zur Blattebene abzusenken.&lt;br /&gt;
&lt;br /&gt;
In einem zweiten Schritt wird dann rückwärts überprüft, wie weit das Element wieder angehoben werden muss. Im günstigsten Fall (sehr große Felder mit nur wenigen [[Dublette (Datenbank)|Dubletten]]) kann dabei fast die Hälfte der insgesamt nötigen Vergleiche bei mäßigem Zusatzaufwand eingespart werden.&lt;br /&gt;
&lt;br /&gt;
Weniger geeignet ist BottomUp-Heapsort zur Sortierung kleinerer Felder mit einfacher numerischer Vergleichsoperation und dann, wenn im Feld sehr viele Elemente gleichwertig sind (dann stimmt die Annahme nicht, dass meist bis in die Nähe der Blattebene abgesenkt werden muss).&lt;br /&gt;
&lt;br /&gt;
== Algorithmus ==&lt;br /&gt;
&lt;br /&gt;
Konkret wird der Heapsort-Algorithmus, was das Absenken betrifft, wie folgt verändert:&lt;br /&gt;
&lt;br /&gt;
Zunächst wird der Pfad, in welchem das Wurzelelement versenkt werden soll, bestimmt. Dies geschieht durch die Ermittlung des jeweils größten Kindes (Pfad maximaler Kinder). Danach wird dieser bestimmte Pfad von unten nach oben (vom Blatt in Richtung Wurzel) durchlaufen. Hierbei wird bei jedem besuchten Knoten verglichen, ob er größer als das abzusenkende Wurzelelement ist. Ist dem so, wird das Wurzelelement an die Position des zuletzt besuchten Knotens kopiert und vorher der restliche Pfad um eine Ebene nach oben verschoben.&lt;br /&gt;
&lt;br /&gt;
Alternativ kann man auch die Verschiebung von vornherein auf Verdacht bis zur Blattebene durchführen und später – soweit notwendig – wieder rückgängig machen. Wo Kopien relativ günstig durchgeführt werden können (weil etwa nur ein [[Zeiger (Informatik)|Zeiger]] kopiert wird), kann das insgesamt vorteilhaft sein.&lt;br /&gt;
&lt;br /&gt;
== Beispiel ==&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Heap&amp;#039;&amp;#039;&amp;#039;: [9, 23, 24, 20, 18, 14, 17, 13, 15, 11, 10, 5, 7, 3, 2]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Baumstruktur:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
[[Datei:Bottom-Up-Heapsort 01.svg|mini|ohne]]&lt;br /&gt;
&lt;br /&gt;
Das Element &amp;#039;&amp;#039;&amp;#039;9&amp;#039;&amp;#039;&amp;#039; muss abgesenkt werden, da es kleiner als mindestens ein Nachfolgeknoten ist.&lt;br /&gt;
Es wird als erstes der Pfad der maximalen Kinder (ausgehend von der Wurzel) bestimmt. Es ergibt sich also &amp;#039;&amp;#039;&amp;#039;9 - 24 - 17 - 3&amp;#039;&amp;#039;&amp;#039;.&lt;br /&gt;
Der Algorithmus durchläuft diesen Pfad nun von unten nach oben, also &amp;#039;&amp;#039;&amp;#039;3 → 17 → 24 → 9&amp;#039;&amp;#039;&amp;#039;. Nun wird der Pfad vom Blattknoten &amp;#039;&amp;#039;&amp;#039;(3)&amp;#039;&amp;#039;&amp;#039; beginnend solange durchlaufen, bis sich ein Knoten findet, der größer als &amp;#039;&amp;#039;&amp;#039;9&amp;#039;&amp;#039;&amp;#039; ist. Der Durchlauf endet folglich bei &amp;#039;&amp;#039;&amp;#039;17&amp;#039;&amp;#039;&amp;#039;. Nun werden alle Knoten ab &amp;#039;&amp;#039;&amp;#039;17&amp;#039;&amp;#039;&amp;#039; bis zum Nachfolgeknoten der Wurzel &amp;#039;&amp;#039;&amp;#039;(= 17 → 24)&amp;#039;&amp;#039;&amp;#039; um eine Ebene nach oben und der Knoten &amp;#039;&amp;#039;&amp;#039;9&amp;#039;&amp;#039;&amp;#039; an die Position von &amp;#039;&amp;#039;&amp;#039;17&amp;#039;&amp;#039;&amp;#039; verschoben. Folglich ändern &amp;#039;&amp;#039;&amp;#039;17&amp;#039;&amp;#039;&amp;#039; und &amp;#039;&amp;#039;&amp;#039;24&amp;#039;&amp;#039;&amp;#039; als Nachfolgeknoten und &amp;#039;&amp;#039;&amp;#039;9&amp;#039;&amp;#039;&amp;#039; als Wurzelknoten ihren Platz.&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Heap&amp;#039;&amp;#039;&amp;#039;: [24, 23, 17, 20, 18, 14, 9, 13, 15, 11, 10, 5, 7, 3, 2]&lt;br /&gt;
&lt;br /&gt;
&amp;#039;&amp;#039;&amp;#039;Baumstruktur:&amp;#039;&amp;#039;&amp;#039;&lt;br /&gt;
&lt;br /&gt;
{{Mehrere Bilder&lt;br /&gt;
| align       = left&lt;br /&gt;
| Richtung    = horizontal&lt;br /&gt;
| Bild1       = Bottom-Up-Heapsort 02.svg&lt;br /&gt;
| Untertitel1 = &lt;br /&gt;
| Breite1     = 250&lt;br /&gt;
| Bild2       = Bottom-Up-Heapsort 03.svg&lt;br /&gt;
| Untertitel2 = &lt;br /&gt;
| Breite2     = 250&lt;br /&gt;
}}&lt;br /&gt;
&amp;lt;div style=&amp;quot;clear:both&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Implementierung ==&lt;br /&gt;
&lt;br /&gt;
Einfache Beispielsimplementierung in [[Varianten der Programmiersprache C#C99|C99]]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;syntaxhighlight lang=&amp;quot;C&amp;quot;&amp;gt;&lt;br /&gt;
 int heapsort_bu( int data[], int n ) // zu sortierendes Feld und seine Länge&lt;br /&gt;
 {&lt;br /&gt;
   int val, parent, child;&lt;br /&gt;
   int root= n &amp;gt;&amp;gt; 1;                  // erstes Blatt im Baum&lt;br /&gt;
   int count= 0;                      // Zähler für Anzahl der Vergleiche&lt;br /&gt;
&lt;br /&gt;
   for ( ; ; )&lt;br /&gt;
   {&lt;br /&gt;
     if ( root ) {                    // Teil 1: Konstruktion des Heaps&lt;br /&gt;
       parent= --root;&lt;br /&gt;
       val= data[root];               // zu versickernder Wert&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     if ( --n ) {                     // Teil 2: eigentliche Sortierung&lt;br /&gt;
       val= data[n];                  // zu versickernder Wert vom Heap-Ende&lt;br /&gt;
       data[n]= data[0];              // Spitze des Heaps hinter den Heap in&lt;br /&gt;
       parent= 0;                     //   den sortierten Bereich verschieben&lt;br /&gt;
     }&lt;br /&gt;
     else                             // Heap ist leer; Sortierung beendet&lt;br /&gt;
       break;&lt;br /&gt;
&lt;br /&gt;
     while ( (child= (parent + 1) &amp;lt;&amp;lt; 1) &amp;lt; n )  // zweites (!) Kind;&lt;br /&gt;
     {                                         // Abbruch am Ende des Heaps&lt;br /&gt;
       if ( ++count, data[child-1] &amp;gt; data[child] )  // größeres Kind wählen&lt;br /&gt;
         --child;&lt;br /&gt;
&lt;br /&gt;
       data[parent]= data[child];     // größeres Kind nach oben rücken&lt;br /&gt;
       parent= child;                 // in der Ebene darunter weitersuchen&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     if ( child == n )                // ein einzelnes Kind am Heap-Ende&lt;br /&gt;
     {                                //   ist übersprungen worden&lt;br /&gt;
       if ( ++count, data[--child] &amp;gt;= val ) {  // größer als der zu versick-&lt;br /&gt;
         data[parent]= data[child];   //   ernde Wert, also noch nach oben&lt;br /&gt;
         data[child]= val;            // versickerten Wert eintragen&lt;br /&gt;
         continue;&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       child= parent;                 // 1 Ebene nach oben zurück&lt;br /&gt;
     }&lt;br /&gt;
     else&lt;br /&gt;
     {&lt;br /&gt;
       if ( ++count, data[parent] &amp;gt;= val ) {  // das Blatt ist größer als der&lt;br /&gt;
         data[parent]= val;           //   zu versickernde Wert, der damit&lt;br /&gt;
         continue;                    //   direkt eingetragen werden kann&lt;br /&gt;
       }&lt;br /&gt;
&lt;br /&gt;
       child= (parent - 1) &amp;gt;&amp;gt; 1;      // 2 Ebenen nach oben zurück&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     while ( child != root )          // maximal zum Ausgangspunkt zurück&lt;br /&gt;
     {&lt;br /&gt;
       parent= (child - 1) &amp;gt;&amp;gt; 1;      // den Vergleichswert haben wir bereits&lt;br /&gt;
                                      //   nach oben verschoben&lt;br /&gt;
       if ( ++count, data[parent] &amp;gt;= val )  // größer als der zu versickernde&lt;br /&gt;
         break;                             //   Wert, also Position gefunden&lt;br /&gt;
&lt;br /&gt;
       data[child]= data[parent];     // Rückverschiebung nötig&lt;br /&gt;
       child= parent;                 // 1 Ebene nach oben zurück&lt;br /&gt;
     }&lt;br /&gt;
&lt;br /&gt;
     data[child]= val;                // versickerten Wert eintragen&lt;br /&gt;
   }&lt;br /&gt;
&lt;br /&gt;
   return count;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Zu Vergleichszwecken gibt die Funktion die Anzahl der durchgeführten Vergleiche zurück.&lt;br /&gt;
&lt;br /&gt;
== Literatur ==&lt;br /&gt;
* J. W. J. Williams: &amp;#039;&amp;#039;Algorithm 232 – Heapsort&amp;#039;&amp;#039;. In: &amp;#039;&amp;#039;Communications of the ACM&amp;#039;&amp;#039;, 1964, 7(6), S. 347–348.&lt;br /&gt;
* Robert W. Floyd: &amp;#039;&amp;#039;Algorithm 245 – Treesort 3&amp;#039;&amp;#039;. In: &amp;#039;&amp;#039;Communications of the ACM&amp;#039;&amp;#039;, 1964, 7(12), S. 701.&lt;br /&gt;
* S. Carlsson: &amp;#039;&amp;#039;HEAPS&amp;#039;&amp;#039;. Doctoral dissertation, Lund Univ., Sweden 1986.&lt;br /&gt;
* Svante Carlsson: &amp;#039;&amp;#039;Average-case results on heapsort&amp;#039;&amp;#039;. In: &amp;#039;&amp;#039;BIT&amp;#039;&amp;#039;, 27, 1987, no.1, S. 2–17.&lt;br /&gt;
* Ingo Wegener: &amp;#039;&amp;#039;BOTTOM-UP-HEAPSORT, a new variant of HEAPSORT beating, on an average, QUICKSORT (if n is not very small)&amp;#039;&amp;#039;. 15th International Symposium on Mathematical Foundations of Computer Science (MFCS ’90) Banská Bystrica, 1990. In: &amp;#039;&amp;#039;Theoret. Comput. Sci.&amp;#039;&amp;#039;, 118, 1993, no. 1, S. 81–98.&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Sortieralgorithmus]]&lt;/div&gt;</summary>
		<author><name>imported&gt;Leyo</name></author>
	</entry>
</feed>