„Bucketsort“ – Versionsunterschied
[ungesichtete Version] | [ungesichtete Version] |
Head (Diskussion | Beiträge) Komplexität |
Head (Diskussion | Beiträge) K tabelle |
||
Zeile 46: | Zeile 46: | ||
<table border="1"> |
<table border="1"> |
||
<tr><td>0</td><td>Baden-Württemberg</td> <td>8</td><td>Niedersachsen</td></tr> |
<tr><td>0</td><td>Baden-Württemberg</td> |
||
<td rowspan="8" width="7"></td> |
|||
<td>8</td><td>Niedersachsen</td></tr> |
|||
<tr><td>1</td><td>Bayern</td> |
<tr><td>1</td><td>Bayern</td> |
||
<td>9</td><td>Nordrhein-Westfalen</td></tr> |
|||
<tr><td>2</td><td>Berlin</td> |
<tr><td>2</td><td>Berlin</td> |
||
<td>10</td><td>Rheinland-Pfalz</td></tr> |
|||
<tr><td>3</td><td>Brandenburg</td> |
<tr><td>3</td><td>Brandenburg</td> |
||
<td>11</td><td>Saarland</td></tr> |
|||
<tr><td>4</td><td>Bremen</td> |
<tr><td>4</td><td>Bremen</td> |
||
<td>12</td><td>Sachsen</td></tr> |
|||
<tr><td>5</td><td>Hamburg</td> |
<tr><td>5</td><td>Hamburg</td> |
||
<td>13</td><td>Sachsen-Anhalt</td></tr> |
|||
<tr><td>6</td><td>Hessen</td> |
<tr><td>6</td><td>Hessen</td> |
||
<td>14</td><td>Schleswig-Holstein</td></tr> |
|||
<tr><td>7</td><td>Mecklenburg-Vorpommern</td> <td>15</td><td>Thüringen</td></tr> |
<tr><td>7</td><td>Mecklenburg-Vorpommern</td> |
||
<td>15</td><td>Thüringen</td></tr> |
|||
</table> |
</table> |
||
Version vom 31. August 2003, 20:48 Uhr
BucketSort (von engl. bucket - Eimer) ist ein schnelles, stabiles Sortierverfahren, das eine Liste in linearer Laufzeit sortieren kann.
Voraussetzungen
Damit eine Liste mit BucketSort sortierbar ist, muss die Anzahl der von den Sortierschlüsseln annehmbaren Werte endlich sein.
BucketSort ist also etwa gut geeignet, um eine Adressliste nach Postleitzahlen zu ordnen, aber nicht, um ein Personenverzeichnis nach Namen zu sortieren, da die Zahl der denkbaren Namen praktisch unendlich ist.
Hilfreich ist außerdem, dass die Sortierschlüssel ganze Zahlen sind, da diese als Indizes eines Feldes (Arrays) verwendet werden können. Ist dies nicht der Fall, so ist eine zusätzliche bijektive Funktion nötig, die jedem möglichen Schlüsselwert eine Zahl zuordnet, sowie die dazugehörige Umkehrfunktion.
Prinzip
BucketSort zählt die Häufigkeit jedes Schlüsselwertes in einer Liste. Daraus errechnet es die korrekte Position jedes Elements und fügt es in einer zweiten Liste dort ein.
Die Häufigkeit der Schlüsselwerte wird in einem so genannten Histogramm gespeichert. Dies wird meist als Array implementiert, das so lang ist, wie es mögliche Schlüsselwerte gibt; als Indizes werden dabei die Schlüsselwerte bzw. die ihnen zugeordneten ganzen Zahlen gewählt. Elemente mit gleichem Sortierschlüssel werden dabei in Gruppen, so genannten Buckets, zusammengefasst.
Das Histogramm wird zunächst mit Nullen initialisiert. Dann wird die zu sortierende Liste durchlaufen und bei jedem Listenelement der entsprechende Histogrammeintrag um eins erhöht.
In einem zweiten Array, das ebenso lang ist wie das Histogramm-Array und ebenfalls mit Nullen initialisiert wird, werden nun die aus dem Histogramm errechneten Einfügepositionen gespeichert.
Schließlich werden in eine Liste, die ebenso lang ist wie die zu sortierende, die Elemente der zu sortierenden Liste nacheinander an den berechneten Positionen eingefügt.
Beispiel
Es liegt eine alphabetisch nach Namen geordnete Liste von Städten vor:
- Aachen (Nordrhein-Westfalen)
- Augsburg (Bayern)
- Bonn (Nordrhein-Westfalen)
- Bremerhaven (Bremen)
- Cuxhaven (Niedersachsen)
- Dresden (Sachsen)
- Erfurt (Thüringen)
- Essen (Nordrhein-Westfalen)
- Frankfurt am Main (Hessen)
- München (Bayern)
- Nürnberg (Bayern)
- Rosenheim (Bayern)
- Rostock (Mecklenburg-Vorpommern)
- Stuttgart (Baden-Württemberg)
- Wiesbaden (Hessen)
Diese Liste soll mit BucketSort alphabetisch nach Bundesländern geordnet werden. Man benötigt nun zunächst eine Funktion, um jedem Bundesland einen Zahlenwert zuzuordnen, so wie es die folgende Tabelle zeigt:
0 | Baden-Württemberg | 8 | Niedersachsen | |
1 | Bayern | 9 | Nordrhein-Westfalen | |
2 | Berlin | 10 | Rheinland-Pfalz | |
3 | Brandenburg | 11 | Saarland | |
4 | Bremen | 12 | Sachsen | |
5 | Hamburg | 13 | Sachsen-Anhalt | |
6 | Hessen | 14 | Schleswig-Holstein | |
7 | Mecklenburg-Vorpommern | 15 | Thüringen |
Somit erhält man das in Abbildung 1 dargestellte Histogramm.
Aus dem Histogramm lassen sich die korrekten Einfügestellen ermitteln. Das Bucket 0 (Baden-Württemberg), das Stuttgart enthält, erhält die Einfügestelle 0.
Die vier bayerischen Städte in Bucket 1 sollen hinter Stuttgart, also ab Position 1, eingefügt werden.
Bremerhaven aus Bucket 4 (Bremen) soll hinter den Buckets 1 und 2 eingefügt werden, also an Position 5. Fährt man fort, erhält man folgendes Array:
Bucket | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
Bundesland | BW | Bay | Ber | Bra | Bre | HH | Hes | MV | NS | NRW | RP | SL | Sac | SA | SH | Thü |
Einfügestelle | 0 | 1 | 5 | 5 | 5 | 6 | 6 | 8 | 9 | 10 | 13 | 13 | 13 | 14 | 14 | 14 |
Nun wird das zu sortierende Feld durchlaufen: zunächst wird Aachen in der Zielliste an Position 10 gespeichert, da die Einfügeposition für den Bucket 9 (Nordrhein-Westfalen) 10 ist. Diese Einfügeposition wird daraufhin auf 11 erhöht, damit der nächste nordrhein-westfälische Ort hinter Aachen eingefügt wird.
Dann wird Augsburg an Position 1 der Zielliste gespeichert, denn dies ist die aktuelle Einfügeposition für Bucket 1 (Bayern). Diese Einfügeposition wird ebenfalls um eins erhöht.
Anschließend wird Bonn hinter Aachen an Position 11 gespeichert usw.
Man erhält die folgende Zielliste:
- Stuttgart (Baden-Württemberg)
- Augsburg (Bayern)
- München (Bayern)
- Nürnberg (Bayern)
- Rosenheim (Bayern)
- Bremerhaven (Bremen)
- Frankfurt am Main (Hessen)
- Wiesbaden (Hessen)
- Rostock (Mecklenburg-Vorpommern)
- Cuxhaven (Niedersachsen)
- Aachen (Nordrhein-Westfalen)
- Bonn (Nordrhein-Westfalen)
- Essen (Nordrhein-Westfalen)
- Dresden (Sachsen)
- Erfurt (Thüringen)
Wie man sieht, sind Städte, die im gleichen Bundesland liegen, untereinander alphabetisch nach den Städtenamen sortiert. Der Grund dafür ist, dass die ursprüngliche Liste nach Städtenamen sortiert war und BucketSort stabil ist.
Komplexität
Die Komplexität von BucketSort ist abhängig von der Länge n der zu sortierenden Liste (im Beispiel: n=15) und der Anzahl k der Werte, die von den Sortierschlüsseln angenommen werden können (im Beispiel: k=16).
Für die Histogramm-Erstellung wird die zu sortierende Liste einmal durchlaufen. Die Komplexität wächst also linear mit der Länge der Liste. Die Aufwandsklasse der Histogramm-Erstellung ist also O(n).
Um die Einfügepositionen zu berechnen, wird das Histogramm einmal durchlaufen. Da das Histogramm-Array so lang ist, wie es mögliche Sortierschlüssel-Werte gibt, ist die Aufwandsklasse für die Erstellung des Einfügestellen-Arrays O(k).
Anschließend wird die zu sortierende Liste erneut durchlaufen, um die Elemente im Zielarray zu speichern. Die Aufwandsklasse ist erneut O(n).
Insgesamt ergibt sich für BucketSort also eine Komplexität von O(n+k).
Implementierung
...