Einführung in die Informatik für Einführung in die Informatik für

Werbung
Dr. Lars Hildebrand
EINI I
Einführung in die Informatik für
Naturwissenschaftler und Ingenieure
Vorlesung
2 SWS
WS 10/11
Dr. Lars Hildebrand
Fakultät für Informatik – Technische Universität Dortmund
[email protected]
http://ls1-www.cs.uni-dortmund.de
EINI Kap. 5 Arrays – Internes Sortieren
1
Thema
Dr. Lars Hildebrand
Kapitel 5
Algorithmen und Datenstrukturen
Konstruktion von Datentypen:
Algorithmen:
Arrays
Sortieren
Unterlagen
Gumm/Sommer, Kapitel 2.7 & 2.8
Echtle/Goedicke, Einführung in die Programmierung mit
Java, dpunkt Verlag, Kapitel 4
Doberkat/Dißmann, Einführung in die objektorientierte
Programmierung mit Java, Oldenbourg, Kapitel 3.4 & 4.1
EINI Kap. 5 Arrays – Internes Sortieren
2
Übersicht
Dr. Lars Hildebrand
Begriffe
Spezifikationen, Algorithmen, formale Sprachen, Grammatik
Programmiersprachenkonzepte
Syntax und Semantik
imperative, objektorientierte, funktionale und logische
Programmierung
Grundlagen der Programmierung
imperative Programmierung
Verfeinerung, elementare Operationen, Sequenz, Selektion, Iteration,
funktionale Algorithmen und Rekursion, Variablen und
Wertzuweisungen, Prozeduren, Funktionen und Modularität
objektorientierte Programmierung
Algorithmen und Datenstrukturen
Berechenbarkeit und Entscheidbarkeit von Problemen
Effizienz und Komplexität von Algorithmen
Programmentwurf, Softwareentwurf
EINI Kap. 5 Arrays – Internes Sortieren
3
Gliederung
Dr. Lars Hildebrand
Arrays
Datenstruktur zur Abbildung gleichartiger Daten
Deklaration
Dimensionierung und Zuordnung von Speicher zur
Laufzeit
Zuweisung: ganzes Array, Werte einzelner Elemente
Speicherfreigabe durch Garbage Collection (Java) oder
explizit (C/C++)
Algorithmen auf Arrays: Beispiel Sortieren
naives Verfahren: Minimum bestimmen, entfernen,
Restmenge sortieren
Heapsort: ähnlich, nur mit Binärbaum über Indexstruktur
Quicksort: divide & conquer, zerlegen in 2 Teilmengen
anhand eines Pivotelementes
EINI Kap. 5 Arrays – Internes Sortieren
4
Arrays, Felder
Dr. Lars Hildebrand
Motivation:
Schleifen erlauben die Verarbeitung mehrerer Daten auf
einen „Schlag“
Eine Entsprechung auf der Variablenseite ist die
Zusammenfassung mehrerer Variablen gleichen Typs: ->
Arrays oder Felder
Beispiele:
Zeichenketten/Strings, Arrays aus Character/Zeichen
Vektoren, Matrizen: Arrays aus Integer/Float Variablen
Abbildung eines Lagerbestandes durch Angabe der
Menge für einen Artikel und einen Lagerort
– Bei n unterschiedlichen Artikeln und m Orten:
– Bestand [1] [5] der Bestand des Artikels 1 am Ort 5
– In Java: Bestand [i] [j] Artikel mit Nummer i und Ort j
EINI Kap. 5 Arrays – Internes Sortieren
5
Arrays, Felder
Dr. Lars Hildebrand
Fragen:
Wie werden Arrays deklariert ?
Wie werden Daten in Arrays abgelegt, verändert,
ausgegeben ?
Wie wird die Größe eines Arrays festgelegt ?
EINI Kap. 5 Arrays – Internes Sortieren
6
Arrays sind Variablen ...
Dr. Lars Hildebrand
... müssen daher auch deklariert werden, bevor sie benutzt
werden
... die viele Variablen enthalten, die vom gleichen Typ sind
... die Anzahl der Dimensionen entspricht der Anzahl der
Indexausdrücke
Deklarationen:
int [] x;
// ein-dimensional int
float [] [] y; // zwei-dimensional float
Legen allerdings anders als bei int z; noch keinen
Speicherplatz fest
EINI Kap. 5 Arrays – Internes Sortieren
7
Arrays
Dr. Lars Hildebrand
Deklarationen einer Array-Variablen legt nur einen Verweis
auf ein Array fest
int [] x;
x = new int [20];
float [] [] y;
y = new float [80][80];
x
y
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
0 1
0 0
.... 79
.... 0
....
.... 79
EINI Kap. 5 Arrays – Internes Sortieren
....
....
....
79 79
....
....
(©M. Goedicke, UGH Essen)
8
Zuweisung an Array - Variable
Dr. Lars Hildebrand
Array-Größe ist fest nach Ausführung des new-Operators
Veränderung der Größe nur durch Umkopieren
int [] a,b;
a = new int [10];
....
// Zuweisung an die Elemente 0 ..9
b = new int [20];
for (int i=0; i < 10; i++) b[i] = a[i];
a = b; // nun verweisen a und b auf das
// gleiche Array!
Beachte: Indizes immer 0 .. Anzahl -1
EINI Kap. 5 Arrays – Internes Sortieren
9
Zuweisungen
Dr. Lars Hildebrand
Bei der Deklaration einer Array-Variablen werden die
Standardwerte zugewiesen
z.B.: int alles 0 ...
Andere Variante:
Belegung mit direkt angegebenen Konstanten
int [] m =
{31,28,31,30,31,30,31,31,30,31,30,31};
Größe und Belegung sind direkt festgelegt
keine Erzeugung mittels new notwendig
Funktioniert auch für mehrdimensionale Arrays:
int [] [] a={{0,1},{11,12},{21,22}};
0 1 2
0
1
11
12
21
22
a[0][0] == 0
a[0][1] == 1
a[1][0] == 11 ...
EINI Kap. 5 Arrays – Internes Sortieren
(©M. Goedicke, UGH Essen)
10
Zuweisung von Array-Variablen ... Beispiel (1)
Dr. Lars Hildebrand
int i = 2;
int [] A;
A = new int [4];
A [0] = 8;
A [i] = 9;
A [1] = 7;
A [3] = 6;
EINI Kap. 5 Arrays – Internes Sortieren
11
Zuweisung von Array-Variablen ... Beispiel (2)
Dr. Lars Hildebrand
...
A [0] = 8;
A [i] = 9;
A [1] = 7;
A [3] = 6;
A = new int [3];
int [] B;
B = A;
EINI Kap. 5 Arrays – Internes Sortieren
12
Zuweisung von Array-Variablen ... Beispiel (3)
Dr. Lars Hildebrand
....
B = A;
A [0] = 6;
B [1] = 7;
B [2] = B [0] + 2;
i = B [0];
A = new int [5];
A [i - 2] = B [1];
B [i - 4] = A.length;
EINI Kap. 5 Arrays – Internes Sortieren
13
Dynamische Größe von Arrays
Dr. Lars Hildebrand
Falls Größe eines Arrays zum Zeitpunkt der Erstellung nicht
bekannt:
die Größe könnte z.B. auch eingelesen werden
In Java kann durch x.length die Anzahl (!) der Elemente dynamisch
bestimmt werden:
int Anz = Eingabe(), Anfangsw = 0;
int [][] Matrix = new int[Anz][Anz +12];
for (int i = 0; i < Matrix.length; i++)
{
for (int j=0; j < Matrix[0].length;j++)
{
Matrix[i][j] = Anfangsw;
}
}
Beachte: Index läuft 0.. Matrix.length -1
EINI Kap. 5 Arrays – Internes Sortieren
14
Berücksichtigung von Typen
Dr. Lars Hildebrand
strenges Typssystem
Für einzelne Elemente eines Arrays, die selbst keine Arrays sind, ist dies
klar:
int [] a = new int [3];
a[1] = 3;
Für Arrays gilt bei Zuweisungen:
Typ der Grundelemente und die Anzahl der Dimensionen muss
übereinstimmen
int [][] a;
...
a = b; // klappt nur, wenn b ebenfalls
// 2-dimensionales int Array ist
EINI Kap. 5 Arrays – Internes Sortieren
15
Komplexe Ausdrücke als Index
Dr. Lars Hildebrand
Beispiel
Bestand der Artikel 3 .. 28 am Ort 4
int Summe = 0;
for (int i=3; i<= 28; i++)
Summe += Bestand[i] [4];
oder ein einfacher Palindrom-Test:
boolean Palindrom = true;
for (int i=1; i<=7/2 && Palindrom; i++)
{
Palindrom = Zeichen[i] == Zeichen[7+1-i];
}
0 1 2 3 4 5 6 7 8
R E N T N E R
1
7
2
6
3
5
(©M. Goedicke, UGH Essen)
EINI Kap. 5 Arrays – Internes Sortieren
16
Arrays: Internes Sortieren
Dr. Lars Hildebrand
Internes Sortieren bringt die Elemente einer Folge in die
richtige Ordnung
Viele Alternativen bzgl. Sortieren sind entwickelt worden
Das einfache interne Sortieren (wie hier vorgestellt) hat
geringen Speicherplatzbedarf aber hohe Laufzeit
Verfahren:
Vertausche Elemente der Folge solange, bis sie in der
richtigen Reihenfolge sind
Hier wird als Speicherungsstruktur ein Array benutzt
EINI Kap. 5 Arrays – Internes Sortieren
17
Zunächst das Einlesen der Werte
Dr. Lars Hildebrand
public class Sortierung
{
public static void main (String [] unbenutzt)
{
int i, j, z, n = Eingabe ();
int [] a = new int [n];
// Lies Elemente ein und gib sie dabei sofort
// wieder aus:
System.out.println ("Die eingegebenen Elemente:");
for (i = 0; i < n; i++)
{ a [i] = Eingabe ();
System.out.print (a [i] + " ");
}
System.out.println ("\n");
...
EINI Kap. 5 Arrays – Internes Sortieren
18
Nun die eigentliche Sortierung ...
Dr. Lars Hildebrand
Die Idee:
Ausgangspunkt: Element an der Stelle i hat den richtigen Platz,
dann müsste eigentlich für alle Elemente an den Stellen
j > i gelten, dass a[i] <= a[j]
Wenn diese Bedingung nicht gilt: vertausche die Elemente an den Stellen i
und j
i
j
Bereits sortiert,d.h.
a[k] ≤a[k+1], f. k≤i-1
und a[k] ≤ a[j], f. k≤i-1 und j ∈{i..n}
EINI Kap. 5 Arrays – Internes Sortieren
19
Nun die eigentliche Sortierung ...
Dr. Lars Hildebrand
Diese Schritte müssen für alle Elemente im Array erledigt
werden
for (i = 0; i < n - 1; i++)
{
// Prüfe, ob a[i] Nachfolger hat, die kleiner als a[i] sind:
for (j = i + 1; j < n; j++)
{
if (a [i] > a [j]) // Ist ein Nachfolger kleiner?
{
// Vertausche a[i] mit a[j]:
// Ringtausch mit Hilfsvariable z
z = a [i];
a [i] = a [j];
a [j] = z;
}
}
}
EINI Kap. 5 Arrays – Internes Sortieren
20
Der Ablauf noch einmal tabellarisch
Dr. Lars Hildebrand
i
0
0
1
2
0
1
3
2
1
3
2
3
j
a [0]
a [1]
a [2]
a [3]
81
95
32
60
81
95
32
60
32
95
81
60
32
95
81
60
32
95
81
60
32
81
95
60
32
81
95
60
32
60
95
81
32
60
95
81
32
60
81
95
(©M. Goedicke, UGH Essen)
EINI Kap. 5 Arrays – Internes Sortieren
21
Ausgabe
Dr. Lars Hildebrand
Zum Schluss wird alles noch ausgegeben
// Gib sortierte Elemente aus:
System.out.println ("Sortierte Elemente:");
for (i = 0; i < n; i++)
System.out.print (a [i] + " ");
System.out.println ("\n");
// Zeilenvorschub.
EINI Kap. 5 Arrays – Internes Sortieren
22
Alternativen
Dr. Lars Hildebrand
Könnte man die Algorithmus Idee auch anders formulieren?
finde Minimum x der aktuellen Menge
positioniere x an den Anfang
sortiere Restmenge nach Entfernen von x
Rekursive Formulierung ?
Weitere Fragen:
Terminierung
Korrektheit
Aufwand, Effizienz
EINI Kap. 5 Arrays – Internes Sortieren
23
Bemerkungen zum Aufwand
Dr. Lars Hildebrand
Der Aufwand wird nach Anzahl der Ausführungen von
Elementaroperationen betrachtet
Im wesentlichen sind das beim Sortieren Vergleiche und
Zuweisungen
Meist begnügt man sich mit einer vergröbernden Abschätzung
Diese Abschätzung wird in der Regel von der Größe des
Problems bestimmt: hier die Anzahl der zu sortierenden
Elemente
Obiges Sortierverfahren:
zwei geschachtelte FOR-Schleifen,
die im schlimmsten Fall über das gesamte Array der
Größe n laufen
Daher ist der Aufwand in der Größenordnung von n2
EINI Kap. 5 Arrays – Internes Sortieren
24
Bemerkungen zum Aufwand
Dr. Lars Hildebrand
Es stellt sich die folgende Frage:
Ist es möglich schnellere Algorithmen zu entwerfen, indem
man die Ermittelung des Maximums beschleunigt?
Antwort
nein!
Jeder Algorithmus, der nur mit Vergleichen zwischen
Schlüsseln arbeitet, benötigt mindestens n − 1 Vergleiche
um das Maximum von n Schlüsseln zu finden.
Beschleunigung also nicht im Auffinden des Maximums
möglich …
EINI Kap. 5 Arrays – Internes Sortieren
25
Sortieren
Dr. Lars Hildebrand
Sortieren: Standardproblem der Informatik
Einfach zu verstehende Aufgabenstellung
Tritt regelmäßig auf
Grundproblem: internes Sortieren
Zu sortierende Menge liegt unsortiert im Speicher vor,
abhängig von der Datenstruktur zur Mengendarstellung
kann (im Prinzip) auf jedes Element zugegriffen werden
Es existieren viele Algorithmen, die nach Algorithmusidee,
nach Speicherplatz und Laufzeit (Berechnungsaufwand)
unterschieden werden
Wir brauchen noch ein formales Gerüst, um Speicherplatz
und Berechnungsaufwand zu charakterisieren !
EINI Kap. 5 Arrays – Internes Sortieren
26
Sortieren
Dr. Lars Hildebrand
Sortieren: Standardproblem der Informatik
Varianten:
Externes Sortieren: Daten liegen auf externem
Speichermedium mit (sequentiellem) Zugriff
Einfügen in sortierte Menge
Verschmelzen von sortierten Mengen
...
Im Folgenden: Effiziente Alternative zum letzten (naiven)
Algorithmus: Heapsort
Verwendung rekursiver Datenstrukturen für rekursive
Algorithmen
EINI Kap. 5 Arrays – Internes Sortieren
27
Rekursive Datenstrukturen
Dr. Lars Hildebrand
Rekursion ist nicht nur ein wichtiges Hilfsmittel für die
Formulierung von Algorithmen, sondern auch für die
Formulierung von Datenstrukturen.
Beispiele
Eine Liste ist ein Einzelelement, gefolgt von einer Liste,
oder die leere Liste.
Eine Menge ist leer oder eine einelementige Menge
vereinigt mit einer Menge.
Oder Bäume (dazu im folgenden mehr).
EINI Kap. 5 Arrays – Internes Sortieren
28
Idee von Baum
Dr. Lars Hildebrand
Künstlerisch
Abstrahiert 1
Abstrahiert 2
Die Informatiksicht:
EINI Kap. 5 Arrays – Internes Sortieren
29
Binärer Baum
Dr. Lars Hildebrand
Definition: (Binärer Baum)
1. Der "leere" Baum ∅ ist ein binärer Baum mit der
Knotenmenge ∅.
2. Seien Bi binäre Bäume mit den Knotenmengen Ki ,
i = 1,2. Dann ist auch B = (w, B1, B2) ein binärer Baum mit
der Knotenmenge
K = {w} ∪∗ K1 ∪∗ K2.
(∪∗ bezeichnet disjunkte Vereinigung.)
3. Jeder binäre Baum B lässt sich durch endlich häufige
Anwendung von 1.) oder 2.) erhalten.
EINI Kap. 5 Arrays – Internes Sortieren
30
Binärer Baum
Dr. Lars Hildebrand
Sprech-/Darstellungsweisen (im Falle 2.)):
Sei B = (w, B1, B2) binärer Baum
w heißt Wurzel, B1 linker und B2 rechter Unterbaum.
Wurzel
w
B1
B2
linker
Unterbaum
rechter
Unterbaum
EINI Kap. 5 Arrays – Internes Sortieren
31
Binärer Baum
Dr. Lars Hildebrand
Darstellung eines Beispiels nach Definition:
B1 = (k1, ∅, (k2, (k3, ∅, ∅), ∅)).
k1
k2
k3
EINI Kap. 5 Arrays – Internes Sortieren
32
Terminologie Binäre Bäume
Dr. Lars Hildebrand
Wurzel
innerer Knoten
Blatt
EINI Kap. 5 Arrays – Internes Sortieren
33
Knotenmarkierter binärer Baum
Dr. Lars Hildebrand
Definition: Sei M eine Menge.
(B, km) ist ein knotenmarkierter binärer Baum
(mit Markierungen aus M)
:⇔
1. B ist binärer Baum (mit Knotenmenge K = K(B))
2. km: K --> M Abbildung.
(Markierung/Beschriftung der Knoten k ∈ K mit
Elementen m ∈ M)
EINI Kap. 5 Arrays – Internes Sortieren
34
Knotenmarkierter binärer Baum
Dr. Lars Hildebrand
Beispiel
M := , := Menge der ganzen Zahlen
Damit existiert auf M eine Ordnung!
"Übliche" Darstellung der Knotenbeschriftung km durch
"Anschreiben" der Beschriftung an/in die Knoten.
24
16
k2
k1
EINI Kap. 5 Arrays – Internes Sortieren
18
k3
35
Eigenschaften eines Heap
Dr. Lars Hildebrand
Ein Heap (Haufen) ist ein knotenmarkierter binärer Baum,
so
dass gilt:
Die Markierungsmenge ist geordnet
im Beispiel: ganze Zahlen
Der binäre Baum ist links-vollständig
Alle Ebenen (vgl. Breitendurchlauf) sind vollständig
besetzt (bis evtl. auf die letzte); die letzte Ebene ist "von
links voll aufgefüllt".
Partiell angeordnete Markierungen
Auf jedem Pfad von der Wurzel zu einem Blatt ist die
Menge der Knotenmarkierungen monoton steigend
angeordnet.
EINI Kap. 5 Arrays – Internes Sortieren
36
Definition: Heap
Dr. Lars Hildebrand
Ein Heap (Haufen) ist ein knotenmarkierter binärer Baum, für
den gilt:
Die Markierungsmenge ist geordnet.
Der binäre Baum ist links-vollständig.
Die Knotenmarkierung der Wurzel ist kleiner oder gleich
der Markierung des linken resp. rechten Sohnes (, sofern
vorhanden).
Die Unterbäume der Wurzel sind Heaps.
An der Wurzel steht das kleinste/eines der kleinsten
Element(e).
EINI Kap. 5 Arrays – Internes Sortieren
37
Beispiel: Heap
Dr. Lars Hildebrand
Binärbaum
Alle Ebene, bis auf letzte vollständig gefüllt
Links-vollständig gefüllt
Knotenmarkierung der Wurzel kleiner als die der Kinder
EINI Kap. 5 Arrays – Internes Sortieren
38
Grobidee zum ADT Heap
Dr. Lars Hildebrand
Datenstruktur
Operationen
Init
Einfügen eines Elementes in einen Heap
Entfernen eines der kleinsten Elemente/des kleinsten
Elementes aus dem Heap und Hinterlassen eines RestHeaps
Zudem:
– Heap ist leer ?/ Heap ist voll ?
– Drucken
– .....
EINI Kap. 5 Arrays – Internes Sortieren
39
Implementierung über Feld
Dr. Lars Hildebrand
Darstellung: Binärer Baum <--> Feld
S[1]
S[2]
S[4]
S[8]
Array
S[1]
S[3]
S[5]
S[6]
S[7]
S[9] S[10] S[11] S[12] S[13] S[14] S[15]
S[2]
S[3]
S[4]
S[12] S[13] S[14] S[15]
EINI Kap. 5 Arrays – Internes Sortieren
40
Implementierung über Feld
Dr. Lars Hildebrand
Beziehung Baum-Feld-Darstellung:
Der Inhalt des i-ten Knotens in der Baumdarstellung wird
im i-ten Feldelement abgelegt.
– Das bedeutet: Baum ebenenweise von links nach
rechts eintragen.
– Das Feldelement a[0] wird nicht verwendet!
Lemma:
Die Söhne des Knotens i in einem Heap haben die
Knotennummern
– 2i
: linker Sohn
– 2i + 1
: rechter Sohn
– Beweis: Induktiv
EINI Kap. 5 Arrays – Internes Sortieren
41
Implementierung über Feld
Dr. Lars Hildebrand
S[1]
Ebene 0
S[2]
Ebene 1
S[4]
Ebene 2
Ebene 3
Array
S[8]
S[1]
S[3]
S[5]
S[6]
S[7]
S[9] S[10] S[11] S[12] S[13] S[14] S[15]
S[2]
S[3]
S[4]
S[12] S[13] S[14] S[15]
In Tiefe i befinden sich die Schlüssel S[2i … 2i+1-1]
EINI Kap. 5 Arrays – Internes Sortieren
42
Implementierung über Feld
Dr. Lars Hildebrand
linker Sohn von S[i] S[2i]
rechter Sohn von S[i] S[2i+1]
Vater von S[i]S[⌊i/2⌋]
Ebene 0
S[3]
Ebene 1
S[6]
Ebene 2
Ebene 3
Array
S[8]
S[7]
S[9] S[10] S[11] S[12] S[13] S[14] S[15]
S[3]
S[12] S[13] S[14] S[15]
EINI Kap. 5 Arrays – Internes Sortieren
43
Heap-Eigenschaft
Dr. Lars Hildebrand
Die Heapeigenschaft wird über die Inhalte definiert
Ein Feld a mit n ganzen Zahlen realisiert einen Heap,
falls a[i/2] ≤ a[i] für alle i= 2, ...., n gilt.
Der Wert des Vaters ist höchstens so groß, wie der der
Söhne
Dabei ist "/" als ganzzahlige Division zu verstehen.
z.B. 5/2 = 2
Verzicht auf Floor( )-Funktion ⌊ ⌋ in der Notation
In einem (Minimum-)Heap, realisiert durch das Feld a, steht
das kleinste Element immer in a[1].
Analog wird der Maximum-Heap definiert
EINI Kap. 5 Arrays – Internes Sortieren
44
Beobachtungen
Dr. Lars Hildebrand
Ein Feld S[1 . . . n] ist ein Heap ab l, wenn der Teilbaum mit
Wurzel l ein Heap ist.
Jedes Feld ist ein Heap ab ⌊n/2⌋ + 1, denn alle Einträge mit
Indices ab ⌊n/2 ⌋ + 1 haben keine Kinder, d.h. der Teilbaum
besteht nur aus einer Wurzel
Ist S[1 . . . n] ein Heap ab l , so ist S ebenfalls ein Heap ab 2l
und 2l + 1.
S[1]
S[2]
S[4]
S[8]
S[1]
S[3]
S[5]
S[6]
S[7]
S[9] S[10] S[11] S[12] S[13] S[14] S[15]
S[2]
S[3]
S[4]
S[12] S[13] S[14] S[15]
EINI Kap. 5 Arrays – Internes Sortieren
45
Operation Einfügen: Algorithmus
Dr. Lars Hildebrand
Eingabe:
Heap a mit n Elementen, neues Element x
Ergebnis:
Heap a mit n+1 Elementen, x seiner Größe gemäß
eingefügt
Vorgehensweise:
Schaffe neuen Knoten n+1, setze a[n+1] = x
Füge also neuen Knoten mit Beschriftung x in den Heap
(evtl.noch an falscher Stelle) ein
Sortiere an richtige Stelle ein
EINI Kap. 5 Arrays – Internes Sortieren
46
Operation Einfügen
Dr. Lars Hildebrand
"An richtige Stelle einsortieren" - Idee:
einsortieren(k) :
k bezeichnet Knotennummer
ist k=1, so ist nichts zu tun,
ist k>1, so geschieht folgendes:
– falls a[k/2] > a[k],
– vertausche a[k/2] mit a[k],
– rufe einsortieren(k/2) auf
Verletzung der
Heap-Eigenschaft
einsortieren ist somit eine rekursive Funktion
EINI Kap. 5 Arrays – Internes Sortieren
47
Beispiel
Dr. Lars Hildebrand
3
6
Vergleich
Vergleich
11
12
18
13
7
11
12
14
Vergleich
9
10
21
15
20
11
18
neuer
Knoten
Einfügen von 11
in unseren Heap
EINI Kap. 5 Arrays – Internes Sortieren
48
Beispiel
Dr. Lars Hildebrand
Neuer Knoten mit k = 13
einsortieren(13)
a[k/2] > a[k] ?
a[6] > a[13] ?
18
> 11 ?
Ja, also tauschen a[6]a[13]
einsortieren(6)
a[k/2] > a[k] ?
a[3] > a[6] ?
12
> 11 ? Ja, also tauschen a[3]a[6]
einsortieren(3)
– a[k/2] > a[k] ?
a[1] > a[3] ?
3
> 11 ?
Nein, fertig
EINI Kap. 5 Arrays – Internes Sortieren
49
Code: einsortieren
Dr. Lars Hildebrand
In das Feld HeapFeld wird richtig einsortiert gemäß:
void einsortieren(int Knoten_Nr) {
if (Knoten_Nr > 1)
{
int Vater_Nr = Knoten_Nr/2;
if (HeapFeld[Knoten_Nr] < HeapFeld[Vater_Nr])
{
Tausche(HeapalsFeld[Knoten_Nr],
HeapalsFeld[Vater_Nr]);
einsortieren(Vater_Nr);
}
}
}
EINI Kap. 5 Arrays – Internes Sortieren
50
Entfernen des kleinsten Elementes
Dr. Lars Hildebrand
Idee einer Hau-Ruck-Lösung:
Entfernen des kleinsten Elements
Baue einen neuen Heap ohne das erste Element auf
z.B. durch sukzessives Einfügen der Elemente in einen
neuen Heap
Nachteil
Berücksichtigt nicht, dass vor dem Entfernen des kleinsten
Elements ein Heap vorliegt
Idee einer effizienteren Lösung
Verwende genau diese Information
EINI Kap. 5 Arrays – Internes Sortieren
51
Erzeugung eines Heaps
Dr. Lars Hildebrand
Wie behält man in diesem Fall einen Heap?
Beobachtung
Jedes Blatt erfüllt die Heapbedingung
Allgemeinere Situation:
Wurzel erfüllt
die Heap-Bedingung ?
Unterbäume sollen
die Heap-Bedingung
erfüllen
EINI Kap. 5 Arrays – Internes Sortieren
52
Erzeugung eines Heaps
Dr. Lars Hildebrand
Idee: Lasse „die Wurzel einsinken“
Vergleiche den Eintrag im Knoten k mit denen seiner
Söhne (soweit vorhanden)
Falls der Eintrag im Knoten k kleiner oder gleich als
diejenigen beider Söhne ist o.k.
Falls der Eintrag des Knotens k größer als der kleinere
Eintrag beider Söhne ist:
– Ermittle den Sohn s mit dem kleineren Eintrag,
– Vertausche den Eintrag des Knotens k mit demjenigen
des Sohnes s,
Wiederhole die Überlegungen mit diesem Knoten s.
EINI Kap. 5 Arrays – Internes Sortieren
53
Beispiel
Dr. Lars Hildebrand
Heap-Bedingung
verletzt
ok
9
12
6
8
Vergleich
86
3
Vergleich
10
15
18
10
13
14
20
EINI Kap. 5 Arrays – Internes Sortieren
54
Code: Heapify
Dr. Lars Hildebrand
void Heapify(int K) {
int LS_Nr = 2*K,
RS_Nr = 2*K + 1,
sel_Sohn;
// Nummer des linken Sohns
// Nummer des rechten Sohns
// Nummer des selektierten Sohns
if (LS_Nr <= AnzahlKnoten && RS_Nr > AnzahlKnoten)
{
// es gibt keinen rechten Sohn
if (HeapFeld[LS_Nr] < HeapFeld[K])
Tausche(HeapFeld[K], HeapFeld[LS_Nr]);
}
else if (RS_Nr <= AnzahlKnoten)
{ // es existieren linker und rechter Sohn
sel_Sohn=(HeapFeld[LS_Nr]<HeapFeld[RS_Nr] ? LS_Nr : RS_Nr);
// wähle den Sohn mit der kleineren Markierung aus.
// Bei Gleichheit wähle den rechten Sohn.
if (HeapFeld[sel_Sohn] < HeapFeld[K])
{ // ist Heap-Bedingung verletzt?
Tausche(HeapFeld[K], HeapFeld[sel_Sohn]);
Heapify(selektierter_Sohn);
}
}
}
EINI Kap. 5 Arrays – Internes Sortieren
55
Anmerkung zur Heapkonstruktion
Dr. Lars Hildebrand
Heapify kann dazu herangezogen werden, aus einem Feld A
mit n Elementen einen Heap zu konstruieren
die Blätter sind bereits Heaps,
hat Knoten k also Blätter zu Söhnen, so erfüllen seine
Unterbäume die Heap-Bedingung,
durchlaufe die Knoten rückwärts von n/2 bis 1 und rufe
Heapify für jeden Knoten auf,
für n >= j >= n/2 ist der Knoten j ein Blatt
EINI Kap. 5 Arrays – Internes Sortieren
56
Anwendung 1: Heapsort
Dr. Lars Hildebrand
Aufgabe: Benutze Heap zum (effizienten) Sortieren.
Heapsort arbeitet in zwei Phasen:
Aufbau eines Heaps aus einem Feld
Schrittweiser Abbau des Heaps
– Auslesen des Wurzelelementes und Entfernen
desselben
– Legen des "letzten" Elementes in die Wurzel
– Rekonstruktion der Heap-Bedingung
für diese restlichen Elemente.
EINI Kap. 5 Arrays – Internes Sortieren
57
Quicksort (nach C.A. Hoare)
Dr. Lars Hildebrand
Gutes Bsp, dass bessere Algorithmen mehr bringen können
als
ausgefeilte, systemnahe Programmierung
Strategie: divide et impera, teile & herrsche, divide & conquer
Idee:
wähle einen Wert w des Sortierfeldes aus
partitioniere Elemente in 2 Teilmengen, die selbst noch
unsortiert sind
– A1, deren Elemente <= w sind,
– A2, deren Elemente >= w sind
sortiere die Teilmengen A1 und A2
(getrennt,
rekursiv)
A1
w Sortierfeldes
A2 nach w
Besonderheit: Partitionierung
des
1 2 ...
k-1 k k+1 ...
n
EINI Kap. 5 Arrays – Internes Sortieren
58
Quicksort
Dr. Lars Hildebrand
Teilalgorithmus zur Partitionierung, (vereinfacht)
wähle w aus dem Array
suche Eintrag an einer Position i von links mit a[i] >= w
suche Eintrag an einer Position j von rechts mit a[j] <= w
vertausche a[i] mit a[j]
wiederhole ab 2. bis i >= j erreicht ist
EINI Kap. 5 Arrays – Internes Sortieren
59
Quicksort
Dr. Lars Hildebrand
Auswahl von w hat Einfluss auf die Güte des Verfahrens
warum ?
Auswahlverfahren:
betrachte a[links], a[(links+rechts)/2], a[rechts]
Variante 1: wähle eines der drei Elemente
Variante 2: wähle das wertmäßig mittlere Element
Erfahrungen:
Variante 1 ist bei zufällig verteilten Daten gut
Variante 2 ist bei ungünstig verteilten Daten gut
EINI Kap. 5 Arrays – Internes Sortieren
60
Quicksort
Dr. Lars Hildebrand
Variante1
jeweils mitte
SORTIERBEISPIEL
li=0
mitte=7
re=14
Variante2,
vorsortieren
li, mitte, re
SORTIERBEISPIEL
BORTIERLEISPIES
BORTIERSEISPIEL
BEIIIEELRTSPROS
BORLIEREEIIPSST
BEIEIEILPTSRROS
BOPLIEIEEIRRSST
BEEEIIILPORRSTS
EINI Kap. 5 Arrays – Internes Sortieren
61
Quicksort
Dr. Lars Hildebrand
void quicksort(char [] A){
int high = A.length-1 ; rekquicksort(A,0,high) ;
}
void rekquicksort(char[] A, int low, int high){
int li = low, re = high, mid = (li+re)/2 ;
if (A[li] > A[mid]) tausche(A,li,mid) ; //Vorsortieren
if (A[mid] > A[re]) tausche(A,mid,re) ; //Vorsortieren
if (A[li] > A[mid]) tausche(A,li,mid) ; //Vorsortieren
if ((re-li) > 2) { // mehr als 3 Werte
char w = A[mid] ; // mittlerer Wert
do {
while (A[li]<w) li++;
// Suche nach
while (w < A[re]) re-- ; // Tauschkandidaten
if (li <= re) { tausche(A,li,re) ; li++ ; re-- ; }
while (li <= re) ;
if (low < re) rekquicksort(A,low,re) ;
if (li < high) rekquicksort(A,li,high) ;
}
}
EINI Kap. 5 Arrays – Internes Sortieren
62
Testfragen
Dr. Lars Hildebrand
Quicksort ist ein rekursiver Algorithmus
Von welcher Art ist die Rekursion ?
Lässt sich die Anzahl rekursiver Aufrufe wie bei Fibonacci durch
akkumulierende Parameter reduzieren ?
Vergleich der Algorithmen
Was ist die Idee/Strategie beim naiven 1. Algorithmus, bei Heapsort,
Quicksort?
Warum terminiert der 1. Algorithmus, Heapsort, Quicksort ?
Warum ist der 1. Algorithmus, Heapsort, Quicksort korrekt ?
Welcher Algorithmus ist besser ?
– Was spricht für den 1. Algorithmus ?
– Was spricht für Heapsort ?
– Was spricht für Quicksort ?
EINI Kap. 5 Arrays – Internes Sortieren
63
Zusammenfassung
Dr. Lars Hildebrand
Arrays
Datenstruktur zur Abbildung gleichartiger Daten
Deklaration
Dimensionierung und Zuordnung von Speicher zur
Laufzeit
Zuweisung: ganzes Array, Werte einzelner Elemente
Speicherfreigabe durch Garbage Collection (Java) oder
explizit (C/C++)
Algorithmen auf Arrays: Beispiel Sortieren
naives Verfahren: Minimum bestimmen, entfernen,
Restmenge sortieren
Heapsort: ähnlich, nur mit Binärbaum über Indexstruktur
Quicksort: divide&conquer, zerlegen in 2 Teilmengen
anhand eines Pivotelementes
Für uns offen: Welches Verfahren ist besser ?
EINI Kap. 5 Arrays – Internes Sortieren
64
Herunterladen