Unterschiede
Hier werden die Unterschiede zwischen zwei Versionen der Seite angezeigt.
Beide Seiten, vorherige Überarbeitung Vorherige Überarbeitung Nächste Überarbeitung | Vorherige Überarbeitung | ||
faecher:informatik:oberstufe:algorithmen:sorting:mergesort:start [15.02.2023 20:09] – [Merge reloaded] Frank Schiebel | faecher:informatik:oberstufe:algorithmen:sorting:mergesort:start [13.02.2025 07:22] (aktuell) – Frank Schiebel | ||
---|---|---|---|
Zeile 10: | Zeile 10: | ||
===== Grundsätzliche Funktionsweise ===== | ===== Grundsätzliche Funktionsweise ===== | ||
- | Mergesort ist eine Divide-and-Conquer Algorithmus, | + | Mergesort ist eine [[faecher: |
* **Teile** das Array in zwei Hälften (Divide). | * **Teile** das Array in zwei Hälften (Divide). | ||
* Sortiere (**rekursiv**) die beiden Hälften (Sort). | * Sortiere (**rekursiv**) die beiden Hälften (Sort). | ||
- | * **Füge** die beiden Hälften wieder zu einen sortierten Array **zusammen** (Merge). | + | * **Füge** die beiden Hälften wieder zu einem sortierten Array **zusammen** (Merge |
Zeile 49: | Zeile 49: | ||
=== (A1) === | === (A1) === | ||
- | Implementiere im Bluej-Projekt https:// | + | Implementiere im Bluej-Projekt https:// |
++++ Hinweis 1: | Da die Eingabe bereits in zwei Teilarrays erfolgt, entfällt der Kopiervorgang aus dem Beispiel - du kannst direkt aus den Arrays a und b in das Array merged einfügen. | ++++ Hinweis 1: | Da die Eingabe bereits in zwei Teilarrays erfolgt, entfällt der Kopiervorgang aus dem Beispiel - du kannst direkt aus den Arrays a und b in das Array merged einfügen. | ||
Zeile 62: | Zeile 62: | ||
int j=0; | int j=0; | ||
- | // k ist läuft von 0 bis merged-length-1 | + | // k läuft von 0 bis merged-length-1 |
// bei jedem Durchlauf muss ein neues Element eingefügt werden - | // bei jedem Durchlauf muss ein neues Element eingefügt werden - | ||
// nur welches? | // nur welches? | ||
Zeile 88: | Zeile 88: | ||
int j=0; | int j=0; | ||
- | // k ist läuft von 0 bis merged-length-1 | + | // k läuft von 0 bis merged-length-1 |
// bei jedem Durchlauf muss ein neues Element eingefügt werden - | // bei jedem Durchlauf muss ein neues Element eingefügt werden - | ||
// nur welches? | // nur welches? | ||
Zeile 97: | Zeile 97: | ||
// Fall 1 und 2 müssen überprüfen, | // Fall 1 und 2 müssen überprüfen, | ||
// Indizes von a und b im erlaubten Bereich befinden. | // Indizes von a und b im erlaubten Bereich befinden. | ||
- | // Was bedeutet das, wenn der INdex außerhalb des erlaubten Bereichs ist? | + | // Was bedeutet das, wenn der Index außerhalb des erlaubten Bereichs ist? |
// Was muss dann geschehen? | // Was muss dann geschehen? | ||
Zeile 149: | Zeile 149: | ||
++++ | ++++ | ||
- | ++++ Lösungsvorschlag | Wenn du auf den Lösungsvorschlag zurückgreifen musstest: Kommentiere den Lösungsvorschlag ausführlich, | + | ++++ Lösungsvorschlag | Wenn du auf den Lösungsvorschlag zurückgreifen musstest: Kommentiere den Lösungsvorschlag ausführlich, |
<code java> | <code java> | ||
int i=0; | int i=0; | ||
Zeile 174: | Zeile 174: | ||
=== (A2) === | === (A2) === | ||
- | Gib den Aufwand | + | Gib zunächst **getrennt** |
===== Mergesort: Versuch 1 ===== | ===== Mergesort: Versuch 1 ===== | ||
Zeile 196: | Zeile 195: | ||
mitte = a.lange/2 | mitte = a.lange/2 | ||
| | ||
- | ta1=teilarray von a von 0 bis mitte | + | ta1=teilarray von a von 0 bis mitte-1 |
- | ta2=teilarray von mitte+1 bis a.laenge-1 | + | ta2=teilarray von mitte bis a.laenge-1 |
| | ||
return merge(msort(ta1), | return merge(msort(ta1), | ||
Zeile 206: | Zeile 205: | ||
* Bewerte die Implementation in Hinsicht auf Ressourcenverbrauch und Effizienz | * Bewerte die Implementation in Hinsicht auf Ressourcenverbrauch und Effizienz | ||
+ | ++++ Lösungsvorschlag | | ||
+ | |||
+ | <code java> | ||
+ | // Mergesort naiv | ||
+ | public String[] msort(String[] a) { | ||
+ | // Implementiere hier gemäß des Pseudocodes im Wiki | ||
+ | if(a.length == 1) { | ||
+ | return a; | ||
+ | } | ||
+ | |||
+ | int mitte = a.length/2; | ||
+ | // Dieser Schritt ist aufwändig! | ||
+ | // Man muss Arrays erzeugen und alle Elemente | ||
+ | // in die neuen Teilarrays hineinkopieren. | ||
+ | // das ist O(n) bei jedem Aufruf :( | ||
+ | String[] ta1 = new String[mitte]; | ||
+ | String[] ta2 = new String[a.length-mitte]; | ||
+ | for(int i=0; i<mitte; i++) { | ||
+ | ta1[i]=a[i]; | ||
+ | } | ||
+ | for(int i=mitte; i< | ||
+ | ta2[i-mitte] = a[i]; | ||
+ | } | ||
+ | return merge(msort(ta1), | ||
+ | } | ||
+ | </ | ||
+ | ++++ | ||
===== Arrayerzeugung ist teuer ===== | ===== Arrayerzeugung ist teuer ===== | ||
- | Prinzipiell funktioniert unser " | + | Prinzipiell funktioniert unser " |
==== Merge reloaded ==== | ==== Merge reloaded ==== | ||
Wir befassen uns zunächst nochmal mit dem Merge-Vorgang und implementieren mit unseren Kenntnissen vom ersten Versuch die Methode | Wir befassen uns zunächst nochmal mit dem Merge-Vorgang und implementieren mit unseren Kenntnissen vom ersten Versuch die Methode | ||
+ | <code java> | ||
public void merge(String[] a, String[] speicher, int min, int mitte, int max) | public void merge(String[] a, String[] speicher, int min, int mitte, int max) | ||
- | | + | </ |
- | in der Vorlage //StandaloneMerge//. Um diese Methode aufrufen zu können, müssen wir die beiden Arrays a und b im Konstruktor zusammenfügen und außerdem ein Speicherarray derselben Länge erzeugen, das man dem Methodenaufruf mitgeben kann. | + | |
+ | in der Klasse '' | ||
---- | ---- | ||
{{: | {{: | ||
- | === (A5) === | + | === (A4) === |
- | * Vollziehe das Zusammenfügen der Arrays, das Erzeugen des Speicher-Arrays und die Bestimmung den Methodenparameter nach | + | * Vollziehe das Zusammenfügen der Arrays, das Erzeugen des Speicher-Arrays und die Bestimmung den Methodenparameter nach. |
- | * Entferne die Kommentarzeichen vor dem Methodenaufruf im Konstruktor | + | * Entferne die Kommentarzeichen vor dem Methodenaufruf im Konstruktor. |
- | Der " | + | Der " |
- | Es ist also wichtig, beim Übertragen der Elemente ins Speicher-Arrays | + | Es ist also wichtig, beim Übertragen der Elemente ins Speicher-Array in der merge Methode bei '' |
<code java> | <code java> | ||
Zeile 242: | Zeile 269: | ||
for(int k=min; k<=max; k++) { | for(int k=min; k<=max; k++) { | ||
- | if(i > mitte) { | + | // Die vier Fälle von oben |
- | a[k] = speicher[j++]; | + | |
- | } else if(j > max) { | + | |
- | a[k] = speicher[i++]; | + | |
- | } else if(less(speicher[j], | + | |
- | a[k] = speicher[j++]; | + | |
- | } else { | + | |
- | a[k] = speicher[i++]; | + | |
- | } | + | |
} | } | ||
Zeile 258: | Zeile 276: | ||
} | } | ||
</ | </ | ||
+ | |||
+ | ---- | ||
+ | {{: | ||
+ | === (A5) === | ||
+ | |||
+ | Vervollständige die Implementierung, | ||
+ | |||
+ | ===== Mergesort mit einem Speicher ===== | ||
+ | |||
+ | Unter Verwendung der neuen Merge-Methode können wir jetzt eine Mergesort Implementation erzeugen, die nicht in jedem Rekursionsschritt neue Arrays erzeugen muss. | ||
+ | |||
+ | {{ : | ||
+ | |||
+ | ---- | ||
+ | {{: | ||
+ | === (A7) === | ||
+ | |||
+ | Im BlueJ-Projekt findest du eine Methode MergeSort, in der dieses Vorgehen vorbereitet ist. Vervollständige die Implementation. | ||
+ | |||
+ | |||
+ | ===== Material ===== | ||
+ | {{simplefilelist>: |