versuche Merge Sort zu verstehen Informatik?
static void msort(int[] array, int left, int right) {
int i, j, k;
int[] b = new int[array.length];
if (right > left) {
int mid = (right + left)/2;
msort(array, left, mid);
msort(array, mid + 1, right);
for (k = left; k <= mid; k++)
b[k] = array[k];
for (k = mid; k < right; k++)
b[right + mid - k] = array[k + 1];
i = left;
j = right;
for (k = left; k <= right; k++) {
if (b[i] < b[j])
array[k] = b[i++];
else
array[k] = b[j--];
}
}
}
static void mergeSort(int[] array) {
msort(array, 0, array.length - 1);
}
Hier werden ja die Werte in umgekehrter Reihenfolge ins hilfsarray b gespeichert, aber weiso ist das notwendig, chat gpt sagt mir wegen speicher, aber geht das ncith auch einfach in dem man die werte normal reinspeichert, weiso umgekehrt?
for (k = mid; k < right; k++)
b[right + mid - k] = array[k + 1];
3 Antworten
Willst Du Mergesort verstehen oder willst Du diese Implementierung verstehen?
Mergesort an sich ist super simpel.
Eine Folge von einem Element ist sortiert. Eine leere Folge auch.
Wenn Du eine längere Folge hast, dann halbiere sie und mache mit jeder halben Folge Mergesort. Danach vereinige beide sortierten Folgen. Du vereinigst (mergest) sie, dadurch, dass Du jeweils das erste Element beider Folgen ansiehst und das größere Element entnimmst und an die sortierte Folge anhängst. Das machst Du so lange, bis beide Folgen leer sind. Das Resultat ist eine lange sortierte Folge.
jo also den algorithmus verstehe ich auch und hab auch einen umgesetzt, aber diesen da oben verstehe ich nur so halb, wieso wird dann bei der 2. forschleife das umgekehrt reingespeichert?
Hier werden ja die Werte in umgekehrter Reihenfolge ins hilfsarray b gespeichert, aber weiso ist das notwendig,
Vermutlich, weil sonst irgendwas überschrieben werden würde. Generell ein nicht einfach zu verstehender Algorithmus. Ich würde erst versuchen, ihn anhand eines Videos zu verstehen. Sich den Code zu merken und Zeile für Zeile zu verstehen ist schon nicht ohne.
ok vielen dank, dachte schon ich würde nur son Knoten im Kopf haben, ich hab den merge sort algorithmus uach anders implementiert aber mit viel mehr zeilen und 2 zusätzlichen arrays in denen ich immer die hälften speichere, funktoinerit auch ist aber eben sclhechter als der da oben, aber der da oben ist auch etwas komplizierter
for (k = left; k <= mid; k++)
b[k] = array[k];
Kopiert das linke zu mergende Teilarray 1:1 nach b.
for (k = mid; k < right; k++)
b[right + mid - k] = array[k + 1];
Kopiert das rechte Teilarray in umgekehrter Reihenfolge nach b.
Es sei left=10, right=20 und mid=30/2=15
left mid right
10 11 12 13 14 15 16 17 18 19 20
Für den rechten Teil gilt:
for (k=15; k<20; k++):
k=15: b[20+15-15] = array [15+1] 20 -> 16
k=16: b[20+15-16] = array [16+1] 19 -> 17
.....
Beim Merge sollen die beiden sortierten Teilarrays sortiert zusammengeführt werden, ich muß also schauen, in welchem Teilarray das nächstgrößere Element zu finden ist.
In der Regel wird aber ein Teilarray bereits konsumiert sein, während im anderen noch Elemente sind. Das müßte ich gesondert prüfen. Um mir genau dies zu ersparen, wird der rechte Teil umgedreht und stattdessen von rechts genommen, denn so lässt sich die Schleife einfacher formulieren.
Schau Di ram besten einen Grenzfall an wie:
1 2 3 | 4 5 6 #oder
4 5 6 | 1 2 3 # <- hierrüber sprchen wir jetzt
Ich schaue z.B. 4<=1 ? Nei, 1 nehmen ... und wenn ich die 3 entnommen habe, ist das rechte Teilarray leer. Ich habe also nichts mehr zum Vergleichen und muß das linke Teilaray kopieren, dazu brauchts nen Bounds-Check, damit ich merke, daß ich am Ende angekommen bin.
Jetzt mit Umkehrung:
4 5 6 | 3 2 1
4<=1? 1 nehmen .... 4<=3, 3 nehmen, 4<=6, 4 nehmen ... 6<=6, 6 nehmen. Es entfällt die Sonderbehandlung, weil die benachbarten größten Elemente durch den Vergleich zur Grenze werden. Dadurch reduziert sich die Schleife auf eine fixe Anzahl Vergleiche, ohne irgendein Bounds-Checking o.ä. .
ahhh, jetzt habe ich es verstanden, das rückwerts speichern machen wir also nur , damit diese methode funktioniert ohne extra kopieren der werte, vielen dank du hast mir sehr geholfen
kannst du kurz erklären was du mit "in der regel wird aber ein teilarray bereits konsumiert sein"