Algorithmen und Datenstrukturen
Wintersemester 2013/14
10. Vorlesung
Algorithmen in Java
Krzysztof Fleszar
Lehrstuhl für Informatik I
1
Übersicht
• Berechnung der Potenz für zwei ganze Zahlen
• Klausuraufgabe SS 2010 !
• Berechnung der Cosinus-Funktion
• Klausuraufgabe WS 2010/2011 !
• Standard- und Referenzdatentypen
• Sortieren mit InsertionSort und MergeSort
• Anwendung: Zählen von falsch geordneten Paaren
• Anpassung der Algorithmen
2
Iterative Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
public class Potenz {
public static void main(String[] args) {
int x = 3;
int y = 4;
int potenz = 1;
for (int i = 0; i < y; i++) { //wird y-mal ausgefuehrt
potenz *= x;
}
System.out.println(x + " hoch " + y + " ist " + potenz);
}
}
3
Iterative Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
public class Potenz {
public static void main(String[] args) {
int x = 3;
int y = 4;
Besser:
Potenzberechnung
in eigener Methode
System.out.println(x + " hoch " + y + " ist " + potenz(x,y));
}
}
4
Iterative Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
public class Potenz {
public static void main(String[] args) {
int x = 3;
int y = 4;
System.out.println(x + " hoch " + y + " ist " + potenz(x,y));
}
public static int potenz(int x, int y) {
int potenz = 1;
for (int i = 0; i < y; i++) { //wird y-mal ausgefuehrt
potenz *= x;
}
return potenz;
}
}
5
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
public class Potenz {
public static void main(String[] args) {
int x = 3;
int y = 4;
System.out.println(x + " hoch " + y + " ist " + potenz(x,y));
}
public static int potenz(int x, int y) {
if (y == 0) return 1;
return x * potenz(x, y - 1);
}
}
An Basisfall denken!
๐ฆ
๐ฅ
=๐ฅ⋅
๐ฆ−1
๐ฅ
6
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
public class Potenz {
public static void main(String[] args) {
int x = 3;
int y = 4;
System.out.println(x + " hoch " + y + " ist " + potenz(x,y));
}
public static int potenz(int x, int y) {
if (y == 0) return 1;
return x * potenz(x, y - 1);
}
}
๐ฆ
๐ฅ
=๐ฅ⋅
Wie oft wird potenz aufgerufen?
๐ฆ−1
๐ฅ
๐ฆ + 1 -mal
7
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Geht es besser?
๐ฆ
๐ฅ =๐ฅ
๐ฆ
๐ฅ =๐ฅ
๐ฆ ⁄2
⋅๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
⋅๐ฅ
๐ฆ ⁄2
falls ๐ฆ gerade
⋅ ๐ฅ falls ๐ฆ ungerade
8
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Geht es besser?
๐ฆ
๐ฅ =๐ฅ
๐ฆ
๐ฅ =๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
⋅๐ฅ
⋅๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
falls ๐ฆ gerade
⋅ ๐ฅ falls ๐ฆ ungerade
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2) * potenz(x, y / 2);
if (y % 2 == 0) return p;
return p * x;
9
}
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Rekursionsgleichung (๐ = ๐ฆ):
๐ ๐ = 2๐ ๐⁄2 + Θ 1
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2) * potenz(x, y / 2);
if (y % 2 == 0) return p;
return p * x;
10
}
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Rekursionsgleichung:
๐ ๐ = 2๐ ๐⁄2 + Θ 1
๐
๐
๐ ๐
๐ ∈ ๐ ๐1−๐
log ๐ ๐ = log 2 2 = 1
z.B. für ๐ = 0,5
Also gilt mit Fall 1 des Master-Theorems:
๐∈Θ ๐
11
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Geht es besser?
๐ฆ
๐ฅ =๐ฅ
๐ฆ
๐ฅ =๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
⋅๐ฅ
⋅๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
falls ๐ฆ gerade
⋅ ๐ฅ falls ๐ฆ ungerade
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2) * potenz(x, y / 2);
if (y % 2 == 0) return p;
return p * x;
12
}
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Geht es besser?
๐ฆ
๐ฅ =๐ฅ
๐ฆ
๐ฅ =๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
⋅๐ฅ
⋅๐ฅ
๐ฆ ⁄2
๐ฆ ⁄2
falls ๐ฆ gerade
⋅ ๐ฅ falls ๐ฆ ungerade
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2);
if (y % 2 == 0) return p * p;
return p * p * x;
}
13
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Rekursionsgleichung (๐ = ๐ฆ):
๐ ๐ = ๐ ๐⁄2 + Θ 1
๐
๐
๐ ๐
log ๐ ๐ = log 2 1 = 0
๐∈Θ 1
Also gilt mit Fall 2 des Master-Theorems:
๐ ∈ Θ log ๐
14
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Wie oft wird potenz aufgerufen?
๐ฆ wird in jedem Aufruf mindestens um
die Hälfte verringert.
Für ๐ฆ = 2๐ gibt es ๐ + 2 = log 2 ๐ฆ + 2 Aufrufe.
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2);
if (y % 2 == 0) return p * p;
return p * p * x;
}
15
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Wie oft wird potenz aufgerufen?
๐ฆ wird in jedem Aufruf mindestens um
die Hälfte verringert.
Es gibt
log 2 ๐ฆ + 2
Aufrufe!
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2);
if (y % 2 == 0) return p * p;
return p * p * x;
}
16
Rekursive Berechnung der Potenz
Berechnung der Potenz ๐ฅ ๐ฆ für zwei ganze Zahlen ๐ฅ und ๐ฆ.
Wie oft wird potenz aufgerufen?
๐ฆ wird in jedem Aufruf mindestens um
die Hälfte verringert.
Es gibt
Θ log ๐ฆ
Aufrufe!
public static int potenz(int x, int y) {
if (y == 0) return 1;
int p = potenz(x, y / 2);
if (y % 2 == 0) return p * p;
return p * p * x;
}
17
Übersicht
• Berechnung der Potenz für zwei ganze Zahlen
• Klausuraufgabe SS 2010 !
• Berechnung der Cosinus-Funktion
• Klausuraufgabe WS 2010/2011 !
• Standard- und Referenzdatentypen
• Sortieren mit InsertionSort und MergeSort
• Anwendung: Zählen von falsch geordneten Paaren
• Anpassung der Algorithmen
18
Berechnung der Cosinus-Funktion
cos 71.356° =
180°
360°
?
19
Berechnung der Cosinus-Funktion
1
cos ๐ฅ cos ๐ฆ = cos ๐ฅ − ๐ฆ + cos ๐ฅ + ๐ฆ
2
20
Berechnung der Cosinus-Funktion
1
cos ๐ฅ cos ๐ฆ = cos ๐ฅ − ๐ฆ + cos ๐ฅ + ๐ฆ
2
โบ cos ๐ฅ + ๐ฆ = 2cos ๐ฅ cos ๐ฆ − cos ๐ฅ − ๐ฆ
⇒ cos 2๐ฅ = 2cos 2 ๐ฅ −1
๐ฅ
2
⇒ cos ๐ฅ = 2cos −1
2
21
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
public class Cosinus {
public static void main(String[] args) {
for (double i = 0; i <= 360; i += 15) {
System.out.println("cos " + i + " = "
+ cos(i * Math.PI / 180.0));
}
}
public static double cos(double x) {
return 2.0 * cos(x / 2.0) * cos(x / 2.0) - 1;
}
}
22
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
public class Cosinus {
public static void main(String[] args) {
for (double i = 0; i <= 360; i += 15) {
System.out.println("cos " + i + " = "
+ cos(i * Math.PI / 180.0));
}
}
public static double cos(double x) {
double cosX2 = cos(x / 2.0);
return 2.0 * cosX2 * cosX2 - 1;
}
}
23
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
Näherung für kleine Winkel (๐ฅ < 0.001): cos ๐ฅ = 1
public static double cos(double x) {
if (x < 0.001) return 1;
double cosX2 = cos(x / 2.0);
return 2.0 * cosX2 * cosX2 - 1;
}
180°
360°
24
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
Ausgabe:
cos
cos
cos
cos
0.0 = 1.0
15.0 = 1.0
30.0 = 1.0
45.0 = 1.0
โฎ
cos 360.0 = 1.0
public static double cos(double x) {
if (x < 0.001) return 1;
double cosX2 = cos(x / 2.0);
return 2.0 * cosX2 * cosX2 - 1;
}
25
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
Näherung für kleine Winkel (๐ฅ < 0.001):
1 2
cos ๐ฅ = 1 − ๐ฅ
2
public static double cos(double x) {
if (x < 0.001) return 1 – 0.5 * x * x;
double cosX2 = cos(x / 2.0);
return 2.0 * cosX2 * cosX2 - 1;
}
180°
360°
26
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
2
Näherung für kleine Winkel (๐ฅ < 0.001):
1 2
cos ๐ฅ = 1 − ๐ฅ
2
1,5
1
0,5
0
0
50
100
150
200
250
300
350
400
-0,5
-1
-1,5
27
Berechnung der Cosinus-Funktion
๐ฅ
cos ๐ฅ = 2cos −1
2
Achtung: Verwende besser Methode cos
der Klasse java.lang.Math
2
28
Übersicht
• Berechnung der Potenz für zwei ganze Zahlen
• Klausuraufgabe SS 2010 !
• Berechnung der Cosinus-Funktion
• Klausuraufgabe WS 2010/2011 !
• Standard- und Referenzdatentypen
• Sortieren mit InsertionSort und MergeSort
• Anwendung: Zählen von falsch geordneten Paaren
• Anpassung der Algorithmen
29
Methoden mit Standarddatentypen
Inkrementieren einer Zahl a .
public class Zaehler {
public static void main(String[] args) {
int a = 1;
inkrementiere(a);
System.out.println("a = " + a);
}
public static void inkrementiere(int a) {
a++;
}
}
Ausgabe:
a = 1
30
Methoden mit Standarddatentypen
Inkrementieren einer Zahl a .
public class Zaehler {
public static void main(String[] args) {
int a = 1;
inkrementiere(a);
System.out.println("a = " + a);
}
public static void inkrementiere(int a) {
a++;
}
}
Bei Standarddatentypen wird Wert
von Variablen übergeben.
31
Methoden mit Standarddatentypen
Inkrementieren einer Zahl a .
public class Zaehler {
public static void main(String[] args) {
int a = 1;
a = inkrementiere(a);
System.out.println("a = " + a);
}
public static int inkrementiere(int a) {
return a + 1;
}
}
32
Methoden mit Referenzdatentypen
Inkrementieren der Zahlen in einem Feld.
public class FeldZaehler {
public static void main(String[] args) {
int[] A = {1, 3, 2, 4};
inkrementiere(A);
for (int i = 0; i < A.length; i++)
System.out.println("A" + i + " = " + A[i]);
}
public static void inkrementiere(int[] A) {
for (int i = 0; i < A.length; i++) A[i]++;
}
}
33
Methoden mit Referenzdatentypen
Inkrementieren der Zahlen in einem Feld.
public class FeldZaehler {
public static void main(String[] args) {
int[] A = {1, 3, 2, 4};
inkrementiere(A);
for (int i = 0; i < A.length; i++)
System.out.println("A" + i + " = " + A[i]);
}
public static void inkrementiere(int[] a) {
for (int i = 0; i < A.length; i++) a[i]++;
}
}
34
Ausgabe:
A0 = 2
A1 = 4
A2 = 3
A3 = 5
Methoden mit Referenzdatentypen
Inkrementieren der Zahlen in einem Feld.
public class FeldZaehler {
public static void main(String[] args) {
int[] A = {1, 3, 2, 4};
inkrementiere(A);
for (int i = 0; i < A.length; i++)
System.out.println("A" + i + " = " + A[i]);
}
public static void inkrementiere(int[] A) {
for (int i = 0; i < A.length; i++) A[i]++;
}
}
35
Bei Feldern wird Referenz übergeben.
Methoden mit Referenzdatentypen
Sortieren der Zahlen in einem Feld.
public class Sortierverfahren {
public static void main(String[] args) {
int[] A = {1, 3, 2, 4};
sort(A);
for (int i = 0; i < A.length; i++)
System.out.println("A" + i + " = " + A[i]);
}
public static void sort(int[] A) {
//TODO: Sortierverfahren Deines Vertrauens
}
}
36
Übersicht
• Berechnung der Potenz für zwei ganze Zahlen
• Klausuraufgabe SS 2010 !
• Berechnung der Cosinus-Funktion
• Klausuraufgabe WS 2010/2011 !
• Standard- und Referenzdatentypen
• Sortieren mit InsertionSort und MergeSort
• Anwendung: Zählen von falsch geordneten Paaren
• Anpassung der Algorithmen
37
Sortieren mit InsertionSort
public static void insertionSort(int[] A) {
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
while (i >= 0 && A[i] > key) {
A[i + 1] = A[i];
i--;
InsertionSort(array of int ๐ด)
}
for ๐ = 2 to ๐ด.๐๐๐๐๐๐ do
A[i + 1] = key;
}
๐๐๐ = ๐ด ๐
}
๐ =๐ −1
while ๐ > 0 and ๐ด ๐ > ๐๐๐ do
๐ด ๐+1 =๐ด ๐
๐ = ๐−1
38
๐ด ๐ + 1 = ๐๐๐
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Beispiel:
4,7,1,4,5,6
Wohlstand: 1,2
39
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Beispiel:
4,7,1,4,5,6
Fehlstand: 1,3
40
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Die Folge ๐, ๐ − 1, … , 1 hat die meisten
Fehlstände aller Folgen mit ๐ Zahlen,
๐ ๐−1
nämlich:
2
41
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Anzahl Fehlstände + Anzahl Wohlstände =
(bei verschiedenen
๐ ๐−1
Elementen in ๐ด)
2
42
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Jeder Algorithmus zur Ausgabe aller Fehlstände in
๐จ braucht also im schlechtesten Fall alleine für die
Ausgabe
๐ ๐−1
Operationen.
2
43
Wohlstände und Fehlstände
Sei ๐ด = ๐1 , ๐2 , … , ๐๐ eine Folge natürlicher Zahlen.
Wir nennen ein Indexpaar ๐, ๐ mit 0 < ๐ < ๐ ≤ ๐
• genau dann einen Wohlstand von ๐ด, wenn ๐๐ < ๐๐ .
• genau dann einen Fehlstand von ๐ด, wenn ๐๐ > ๐๐ .
Idee: Fehlstände zählen, nicht ausgeben
44
Fehlstände zählen mit InsertionSort
public static void insertionSort(int[] A) {
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
while (i >= 0 && A[i] > key) {
A[i + 1] = A[i];
i--;
}
A[i + 1] = key;
}
}
45
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
while (i >= 0 && A[i] > key) {
A[i + 1] = A[i];
i--;
fehlstaende++;
}
A[i + 1] = key;
}
return fehlstaende;
}
46
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
In Java
while (i >= 0 && A[i] > key) {
A[i + 1] = A[i];
i--;
fehlstaende++;
}
A[i + 1] = key;
}
return fehlstaende;
}
j = 4
1 2 5 7 3 6
Sortierter Bereich
47
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
Im Pseudocode!
while (i >= 0 && A[i] > key) {
A[i + 1] = A[i];
i--;
fehlstaende++;
}
A[i + 1] = key;
}
return fehlstaende;
}
๐ = 5
1 2 5 7 3 6
Sortierter Bereich
48
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
while (i >= 0 && A[i] > key) {
Behebt alle
A[i + 1] = A[i];
Fehlstände
i--;
fehlstaende++;
๐, 5
}
A[i + 1] = key;
}
return fehlstaende;
}
1 2 5 7 3 6
Sortierter Bereich
49
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
for(int j = 1; j < A.length; j++) {
int key = A[j];
int i = j - 1;
while (i >= 0 && A[i] > key) {
Behebt alle
A[i + 1] = A[i];
Fehlstände
i--;
fehlstaende++;
๐, 5
}
A[i + 1] = key;
}
return fehlstaende;
}
1 2 3 5 7 6
Sortierter Bereich
50
Fehlstände zählen mit InsertionSort
//sortiert a und gibt anzahl fehlstaende zurueck
public static int insertionSort(int[] A) {
int fehlstaende = 0;
Jeder
for(int j = 1; j < A.length; j++) {
Schleifenint key = A[j];
int i = j - 1;
durchlauf
while (i >= 0 && A[i] > key) {
behebt
A[i + 1] = A[i];
i--;
einen
fehlstaende++;
Fehlstand
}
A[i + 1] = key;
}
return fehlstaende;
}
1 2 3 5 7 6
Sortierter Bereich
51
Fehlstände zählen mit InsertionSort
Anzahl Fehlstände
≤ Anzahl Vergleiche bei InsertionSort
≤ Anzahl Fehlstände + ๐ − 1
52
Fehlstände zählen mit MergeSort
MergeSort(array of int ๐ด, int โ = 1, int ๐ = ๐ด.๐๐๐๐๐๐)
if โ < ๐ then
๐ = โ + ๐ ⁄2
MergeSort(๐ด, โ, ๐)
MergeSort(๐ด, ๐ + 1, ๐)
Merge (๐ด, โ, ๐, ๐)
public static void mergeSort(int[] A, int l, int r) {
if (l < r) {
int m = (l + r) / 2;
mergeSort(A, l, m);
mergeSort(A, m + 1, r);
merge(A, l, m, r);
}
53
}
Fehlstände zählen mit MergeSort
MergeSort(array of int ๐ด, int โ = 1, int ๐ = ๐ด.๐๐๐๐๐๐)
public static void mergeSort(int[] A) {
mergeSort(A, 0, A.length - 1);
}
public static void mergeSort(int[] A, int l, int r) {
if (l < r) {
int m = (l + r) / 2;
mergeSort(A, l, m);
mergeSort(A, m + 1, r);
merge(A, l, m, r);
}
54
}
Fehlstände zählen mit MergeSort
MergeSort(array of int ๐ด, int โ = 1, int ๐ = ๐ด.๐๐๐๐๐๐)
public static void mergeSort(int[] A) {
mergeSort(A, 0, A.length - 1);
}
2x gleicher Methodenname erlaubt? Ja, solange Signatur verschieden!
public static void mergeSort(int[] A, int l, int r) {
if (l < r) {
int m = (l + r) / 2;
mergeSort(A, l, m);
mergeSort(A, m + 1, r);
merge(A, l, m, r);
}
55
}
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ =๐+1
1 4 7 2 3 6
๐
๐
โ
56
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ =๐+1
1 4 7 2 3 6
๐
๐
โ
1 4 7∞ 2 3 6∞
๐
๐ฟ
๐
๐
57
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ =๐+1
1 4 7∞
๐
2 3 6∞
๐
58
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ =๐+1
1
1 4 7∞
๐
2 3 6∞
๐
59
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ =๐+1
1 2
1 4 7∞
๐
2 3 6∞
๐
60
Fehlstände zählen mit MergeSort
Merge(array of int ๐ด, int โ, int ๐, int ๐)
๐1 = ๐ − โ + 1
๐2 = ๐ − ๐
let ๐ฟ 1 … ๐1 + 1 and ๐
[1 … ๐2 + 1] be new arrays of int
๐ฟ 1 … ๐1 = ๐ด[โ … ๐]
๐
1 … ๐2 = ๐ด[๐ + 1 … ๐]
๐ฟ ๐1 + 1 = ๐
๐2 + 1 = ∞
๐=๐=1
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐] Wird von Feld ๐
gewählt, so werden
๐ =๐+1
๐ – ๐ + 1 Fehlstände beseitigt. 61
1 2
1 4 7∞
1
๐
2 3 6∞
๐
Fehlstände zählen mit MergeSort
๐=0
for ๐ = โ to ๐ do
if ๐ฟ ๐ ≤ ๐
๐ then
๐ด๐ =๐ฟ ๐
๐=๐ + 1
else
๐ด[๐] = ๐
[๐]
๐ = ๐ + ๐1 − ๐ + 1
๐ =๐+1
return ๐
Fehlstände
lassen sich mit
MergeSort zählen!
Wird von Feld ๐
gewählt, so werden
๐1– ๐ + 1 Fehlstände beseitigt.
62
Fehlstände zählen mit MergeSort
public static int mergeSort(int[] A, int l, int r) {
int fehlstaende = 0;
if (l < r) {
int m = (l + r) / 2;
fehlstaende += mergeSort(A, l, m);
fehlstaende += mergeSort(A, m + 1, r);
fehlstaende += merge(A, l, m, r);
}
return fehlstaende;
}
63
Schluss
Bei Rekursionen
• denkt an den Basisfall/Rekursionsabbruch!
• vermeidet Mehrfachaufrufe mit gleichem Argument
• leitet die Rekursionsgleichungen her!
Aufgabe Wohlstände/Fehlstände
• passt bekannte Algorithmen an
• Ausgabe aller Fehlstände
≠ Ausgabe Anzahl Fehlstände
64