FB18 - Das Forum für Informatik

fb18.de / Diplom Informatik / Unterbereich Grundstudium / Praktische Informatik

BucketSort

BucketSort 2004-02-22 09:48
Anonymer User
Hallo…

kann mir mal jemand schnell den Alg. BucketSort VERSTÄNDLICH (also nicht wie im Script) erklären???

Vielen Dank!

Re: BucketSort 2004-02-22 10:07
UncleOwen
Um welches Skript gehts eigentlich? Und was verstehst Du daran nicht?

Grundsaetzlich gehts bei BucketSort einfach darum, dass alle Eintraege, die mit 'A' beginnen in ein "Bucket" kommen, die mit 'B' beginnen ins naechste, etc. Die einzelnen Buckets kann man dann weiter sortieren.

Re: BucketSort 2004-02-22 11:06
Christoph
wenn die Schlüsselmenge begrenzt bzw. endlich ist, kann man das Verfahren anwenden. Alle Objekte, die den gleichen Schlüssel bekommen (z.B. Anfangsbuchstaben A oder Hashcode 42, wenn es z.B. nur die Codes 1..100 gibt), werden dann "unsortiert" (wonach auch?) in einen Bucket gesteckt.
Wenn man durch ist (in Linearzeit), kann man die Buckets (die man als Listen implementiert hat) einfach zu einer großen Liste verketten (was in Linearzeit zur Schlüsselmenge geht. Diese ist i.A. deutlich kleiner als die Zahl der zu sortierenden Elemente).

Also fertig in Linearzeit. Nur nicht Herrn Valk erzählen, denn er glaubt das einem nicht [img]http://www.fb18.de/gfx/25.gif[/img] (naja, wenn man vergisst, die beschr. Schlüsselmenge zu erwähnen)

Re: BucketSort 2004-02-22 11:36
Zaphod
Wenn man mal unter
"bucket sort" + animation
googelt, findet man mehrere Veranschaulichungen, die einen diese Sortieralgorithmen gut verstehen lassen. Das gilt nicht nur für Bucket Sort. [img]http://www.fb18.de/gfx/23.gif[/img]

Re: BucketSort 2005-02-05 21:49
Fred
Vielleicht hilft Dir meine Implementierung des BucketSort beim Verständnis? [img]http://www.fb18.de/gfx/25.gif[/img]
void bucketsort(char *a, int l) { int n[ 256]={0},j;while(l-->0)n[*a++]++;for(j=255;j>=0;j--)while(n[j]--)*(--a)=j; }

Re: BucketSort 2005-02-05 22:54
UncleOwen
Fred, Du machst mir Angst… so langsam sieht das ja richtig nach C aus, was Du produzierst.

Re: BucketSort 2005-02-05 22:58
Fred
Fred, Du machst mir Angst… so langsam sieht das ja richtig nach C aus, was Du produzierst.
Naja, ich wollte halt mal schauen, ob man einen Sortieralgorithmus in einer Zeile (80 Zeichen) implementieren kann. Wenn man das Leerzeichen in der Arraydeklaration wegnimmt (hab ich nur für die korrekte Darstellung im Forum hinzufügen müssen), kommts gerade hin.

Geht aber wahrscheinlich noch kürzer, oder? Wollen wir einen Wettbewerb starten? [img]http://www.fb18.de/gfx/23.gif[/img]

EDIT: Aus while(l–>0) kann man while(l–) machen, spart nochmal zwei Zeichen.

Re: BucketSort 2005-02-05 23:01
UncleOwen
Wollen wir einen Wettbewerb starten? [img]http://www.fb18.de/gfx/23.gif[/img]

Immer gerne. Aber dazu hätte ich gerne erstmal ordentlich spezifiziert, was Bucketsort _genau_ macht, die Semantik aus Deinem Code rauszupfriemeln hab ich gerade keine Lust drauf *g*

Re: BucketSort 2005-02-05 23:10
Fred
Der Grundgedanke ist folgender: Du hast ein ungeordnetes Array a der Länge l. Der Wertebereich der Elemente des Arrays sollte nicht allzu gross sein, in meinem Beispielcode sinds nur chars, also 256 verschiedene Werte. Jetzt muss man zwei Schritte vornehmen:

1. Die Häufigkeit aller 256 verschiedenen Werte im Array festellen.
Dafür benötigt man ein Array n der Länge 256. Beispiel: n[0] = 7 bedeutet, dass die 0 sieben Mal in dem Array vorkam.

2. Das sortierte Array aus dem "Zählarray" n generieren.
Beispiel: n[0] = 7 bedeutet, dass das Array mit sieben Nullen anfangen muss.

BucketSort benötigt also nur O(n) Speicher und Rechenzeit, was es zu einem sehr effektiven Sortieralgorithmus macht - solange der Wertebereich eben klein genug ist.

Re: BucketSort 2005-02-05 23:27
UncleOwen
Also 5 Bytes hab ich schon gespart. <edit>Mist, das ist ein echtes char-Array, kein String, oder? Dann doch nur 3</edit>

Re: BucketSort 2005-02-05 23:38
Fred
Also 5 Bytes hab ich schon gespart. <edit>Mist, das ist ein echtes char-Array, kein String, oder? Dann doch nur 3</edit>
Drei Bytes habe ich mittlerweile auch einsparen können:
int n[256]={0},j=255;while(l--)n[*a++]++;for(;j>=0;j--)while(n[j]--)*(--a)=j;

Re: BucketSort 2005-02-05 23:42
UncleOwen
Ah, die Initialisierung nach vorne ziehen ist gut. Das eine Byte hab ich woanders gespart: Statt dem j>=0 als Schleifenbedingung tuts auch j+1.

Re: BucketSort 2005-02-05 23:45
UncleOwen
*(–a)
Die Klammern sind unnötig.

Re: BucketSort 2005-02-05 23:49
Fred
Statt dem j>=0 als Schleifenbedingung tuts auch j+1.
Genial! Darauf wäre ich nie gekommen. Zusammen mit den unnötigen Klammern sind wir bereits auf 74 Bytes runter:
int n[256]={0},j=255;while(l--)n[*a++]++;for(;j+1;j--)while(n[j]--)*--a=j;

Re: BucketSort 2005-02-06 01:14
Nigel Menzel
Wenn man j mit 256 initialisiert kann man statt for(;j+1;j--)while(j--)nehmen.

Re: BucketSort 2005-02-06 01:16
Fred
Wenn man j mit 256 initialisiert kann man statt for(;j+1;j--)while(j--)nehmen.
Sehr schön! Mittlerweile sind wir bei 71 Bytes angekommen:
int n[256]={0},j=256;while(l--)n[*a++]++;while(j--)while(n[j]--)*--a=j;

Re: BucketSort 2005-02-06 01:30
MoKrates
Lass doch mal das '={0}' weg. Das initialisiert bloss das erste byte des Arrays auf 0, und wenn das reicht, dann reicht auch gar kein init ;)

Post mal, ob das das immer noch geht.

Mo

Re: BucketSort 2005-02-06 01:35
Fred
Lass doch mal das '={0}' weg. Das initialisiert bloss das erste byte des Arrays auf 0, und wenn das reicht, dann reicht auch gar kein init ;)
Nein, denn es werden nicht nur die angegebenen Bytes initialisiert, sondern auch der Rest mit 0.

Post mal, ob das das immer noch geht.
Die Anweisung in "0x0040ba89" verweist auf Speicher in "0xff12ff22".
Der Vorgang "written" konnte nicht auf dem Speicher durchgeführt werden.

Re: BucketSort 2005-02-06 01:40
Fred
Mit einem
#define w while kann man auch auf 59 Bytes kommen, aber zusammen mit dem #define ist es leider insgesamt mehr:
int n[256]={0},j=256;w(l--)n[*a++]++;w(j--)w(n[j]--)*--a=j;

Re: BucketSort 2005-02-06 01:43
MoKrates
Vielleicht solltest Du w nicht auf while definieren, sondern auf while(, so kannst Du nochmal 2 Bytes sparen.

Das mit der Initialisierung: Dieses neue C ist auch nicht mehr das, was es mal war…

Mo

Re: BucketSort 2005-02-06 01:45
Fred
Vielleicht solltest Du w nicht auf while definieren, sondern auf while(, so kannst Du nochmal 2 Bytes sparen.
Das funktioniert nicht… und dabei hatte ich Dich immer als C-Guru in Erinnerung [img]http://www.fb18.de/gfx/25.gif[/img]

Aber wie wäre es hiermit, mitterlweile sind wir bei 53 Bytes + #define:

#define w(x) while(x--) int n[256]={0},j=256;w(l)n[*a++]++;w(j)w(n[j])*--a=j;

Re: BucketSort 2005-02-06 01:59
MoKrates
Muss j wirklich 256 sein, und nicht 255? Und wenn es 255 sein muss, kann es doch als unsigned char definiert werden, oder? Und dann kannst Du statt 256 doch ~0 schreiben. Spart ein Byte ;)

Mo

Re: BucketSort 2005-02-06 02:04
Fred
Muss j wirklich 256 sein, und nicht 255?
Ja, denn die Schleife
while(j--) soll ja 256 Mal durchlaufen. Der Ausdruck j– ist vor dem ersten Durchlauf 256 und vor dem 256ten 1. Vor dem 257ten ist er 0 und die Schleife bricht ab. Im Schleifenrumpf durchläuft j allerdings die Werte 255 bis 0 (wegen des – hinter dem j).

Und wenn es 255 sein muss, kann es doch als unsigned char definiert werden, oder? Und dann kannst Du statt 256 doch ~0 schreiben. Spart ein Byte ;)
Möglicherweise, aber "unsigned char" ist ein paar Bytes länger als "int"…

Re: BucketSort 2005-02-06 02:05
georg
Muss j wirklich 256 sein, und nicht 255?

Ich denke auch, dass es 255 sein muss.
Edit: Jetzt nicht mehr, Fred's Posting hat mich überzeugt [img]http://www.fb18.de/gfx/23.gif[/img]

Und wenn es 255 sein muss, kann es doch als unsigned char definiert werden, oder? Und dann kannst Du statt 256 doch ~0 schreiben. Spart ein Byte ;)

Mo

Nur leider nimmt das "unsigned char" dafür mehr Platz ein. [img]http://www.fb18.de/gfx/26.gif[/img]

Re: BucketSort 2005-02-06 02:07
georg
Mit einem
#define w while kann man auch auf 59 Bytes kommen

OK, ich kenne sogar ein #define, wenn man das nicht mitzählt,
kommt man auf 1 Byte [img]http://www.fb18.de/gfx/10.gif[/img]

Re: BucketSort 2005-02-06 02:13
Fred
Muss j wirklich 256 sein, und nicht 255?
Ich denke auch, dass es 255 sein muss.
Ich habs gerade nochmal vorsichtshalber getestet. Folgender Code spuckt die Zahlen 255 bis 0 aus:
w(j) printf("%i,", j);
OK, ich kenne sogar ein #define, wenn man das nicht mitzählt,
kommt man auf 1 Byte
Meine Hoffnung dabei ist ja, dass man das #define in vielen Routinen nutzen kann und daher die Platzkosten geteilt werden und so gegen 0 gehen. Aber natürlich hast Du im Grunde genommen Recht.

Re: BucketSort 2005-02-06 02:18
Faleiro
OK, ich kenne sogar ein #define, wenn man das nicht mitzählt,
kommt man auf 1 Byte
Meine Hoffnung dabei ist ja, dass man das #define in vielen Routinen nutzen kann und daher die Platzkosten geteilt werden und so gegen 0 gehen.
LOL, klasse :-))

Re: BucketSort 2005-02-06 02:23
Fred
Meine Hoffnung dabei ist ja, dass man das #define in vielen Routinen nutzen kann und daher die Platzkosten geteilt werden und so gegen 0 gehen.
LOL, klasse :-))
Ey, nicht lachen! In meinem Programm wird sie schon von zwei Routinen genutzt:
#include <stdio.h> #define w(x) while(x--) void bucketsort(unsigned char *a, int l) { int n[256]={0},j=256; [b]w(l)[/b] n[*a++]++; [b]w(j)[/b] [b]w(n[j])[/b] *--a=j; } void print(unsigned char *a, int l) { [b]w(l)[/b] printf(", %i", *a++); printf("_\n"); } int main() { unsigned char a[] = {255, 0, 128, 127, 7, 4, 11, 5, 3, 4, 9, 8, 1, 7, 2}; const int l = 15; print(a, l); bucketsort(a, l); print(a, l); return 0; }