Count Sort Funktion geht zu früh aus der Schleife?
Ich möchte ein Programm schreiben, dass ein Array mit Count Sort sortieren soll. Doch habe ich einen Fehler. Meine Eingabe für das unsortierte Array war:
38 38 19 57 0 18 59 27 18 57 19 47 4 2 5 5 1 1
Aber als Ausgabe bekam ich bloß:
0 1 1 2 4 5 5 0 0 0 0 0 0 0 0 0 0 0
Für dieses Programm sind besonders 2 Funktionen wichtig und ich denke, dass in einen der Beiden mein Fehler ist. Hier ist meine erste Funktion fürs Zählen:
void count(int input_array[], int len, int count_array[])
{
for (i=0; i < len; i++)
{
count_array[i] = 0;
}
for (j=0; j<len;j++)
{
count_array[input_array[j]]++;
}
}
Meine erste For-schleife soll sagen, dass count_array min. 38 Stellen lang sein soll und soll überall mit 0 initialisierst werden. "len" steht für Länge und ist 38.
Die zweite for-Schleife soll das eigentliche Nachzählen tun. zBs. bei j=1 sollte die for-Schleife also im output_array eine 38 finden. Also soll count_array bei der Stelle 38 um eins erhöhen. Das gleiche mit j=2 usw.
Und meine zweite Funktion soll nun das output Array schreiben, welches richtig sortiert ist. k ist der Index im output_array. k ist der Index. Die erste for-Schleife soll das count_array durchgehen und die zweite for-Schleife soll das schreiben der Zahl so oft wiederholen, wie häufig diese gefunden wurde.
void write_output_array(int output_array[], int len, int count_array[])
{
k=0;
for (j=0; j < len; j++)
{
for (i=0; i < count_array[j]; i++)
{
output_array[k] = j;
k++;
}
}
}
Hat jemand eine Idee warum write_output_array wohl früher endet als gewollt?
3 Antworten
Fangen wir mal vorne an:
void count(int input_array[], int len, int count_array[])
{
/* for (i=0; i < len; i++)
{
count_array[i] = 0;
} */
count_array=memset(count_array,0,sizeof(int)*len));
}
Bei der nächsten Schleife ist allerdings schon ein Fehler, wenn len die Länge des Zählarray ist, respektive der größte Wert.
for (j=0; j<len;j++) /* Muß über die Länge des Eingabearray iterieren */
{
count_array[input_array[j]]++;
}
Fange also erstmal damit an, diesen Teil zu korrigieren.
Beachte: Ich habe versehentlich Java als Programmiersprache angenommen, das Prinzip ist aber dasselbe. Du musst wissen, wie lang Dein zu sortierendes Array ist und Du musst die Länge des Zählarrays aus dem Maximum der Werte im zu sortierenden Array bestimmen.
----
Also ich glaube, Du hast hier einen generellen Denkfehler. Abgesehen von dem offensichtlichen Fehler, dass Len in den meisten Fällen nicht der Länge von output_array entspricht.
Das zweite Array "count_array" soll doch für jeden möglichen Wert in der 1. Liste sagen, wie oft er vorkommt, richtig? Somit musst Du doch erstmal das Maximum aller Werte in der ersten Liste ermitteln. Du sagst, das steht in Len - was keinen Sinn ergibt, denn die Länge eines Arrays kann man mit einer Property ganz einfach ermitteln.
Der erste Schritt muss also sein, die Länge des Arrays zu ermitteln, in das Du zählst. Das geht mit
int maxValue = 0;
for (int i = 0; i < output_array.length; i++)
if (maxValue < output_array[i]) maxValue = output_array[i];
Jetzt steht in maxValue die größte Zahl in Deinem Ausgangsrray - egal, wie lang das ist.
Jetzt machst Du das Array, in dem Du zählst. Weil Arrays ab 0 indiziert werden, brauchst Du einen Wert mehr im Array:
int[] count_array = new int[maxValue + 1];
Jetzt läuft doch die erste Funktion auf folgendes raus:
void count(int input_array[], int count_array[])
{
for (i=0; i < count_array.length; i++)
count_array[i] = 0;
for (j=0; j < input_array.length; j++)
count_array[input_array[j]]++;
}
Für die zweite Funktion gilt dasselbe - achte auf die Indizes und die Semantik der Arrays.
Der Rückweg sieht nun wiefolgt aus:
void write_output_array(int output_array[], int count_array[])
{
k=0;
for (j = 0; j < count_array.length; j++)
{
for (i=0; i < count_array[j]; i++)
{
output_array[k++] = j;
}
}
}
EDIT: Ach waddema - ich glaub, ich hab einen Fehler in meiner Denkweise des Algorithmus...
Und ob es nun guter oder schlechter Stil ist, einzeilige "Blöcke" in geschweifte Klammern zu setzen oder nicht, ist eine philosophische Frage, über die man seit Generationen streiten kann ;-)
Ich habe deinen Code verstanden. Er geht schief.
Denk dir mal ein Szenario, bei dem an Stelle 0 im Zählarray eine 0 steht. Dann bricht der Loop sofort ab.
Ja, da hätte ein "count_array[i].length" stehen müssen im for. So war das gedacht. Aber dennoch stimmt die Logik glaube ich nicht ganz.
Ja. Im prinzip passte die Methode, wie sie der Fragensteller zu Anfang hatte.
Einziger Fehler war die falsche Größe des count_arrays soweit ich das sehe.
(Und ein paar Dinge bezüglich Geschwindigkeit udn Speicherverbrauch)
Richtig. Der Rückweg war schon ok, nur, dass als Len kein eigener Parameter sein muss, weil er sich durch Array.length ja ergibt.
Jetzt müsste mein Code auch stimmen ;-)
Stimmt. In den Kommentaren steht C - daher wird das eh nicht funktionieren (weil ich Java geschrieben habe...), aber das Prinzip sollte klar werden. Wenn er in C arbeitet, braucht er eventuell sogar zwei Längenparameter. Einen für das Eingangsarray und einen für das Zählarray.
Dein Problem:
1.) Der count_array muss die Größe von Maximalwert bis Minimalwert haben, nicht len. In deinem falle also 1 bis 59, bzw. 0 bis 59, wenn du dir das Indexverschieben sparen möchtest.
Das sollte nicht funktionieren. Da fehlt der äußere Loop.
Den Check auf größer 0 braucht es nicht, das erledigt die Loop-Bedingung.
(Zudem wäre es angebracht, gleich guten Programmierstil zu lehren und in den anderen Codeblöcken geschweifte Klammern um die Blöcke zu setzen)