Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Praktische Informatik 1

Ähnliche Präsentationen


Präsentation zum Thema: "Praktische Informatik 1"—  Präsentation transkript:

1 Praktische Informatik 1
Prof. Dr. H. Schlingloff

2 Sortieren Oft lohnt es sich, Daten zu sortieren
einmalige Aktion, Abfragen häufig oft gleich beim Eintrag möglich Wie sortiert man eine unsortierte Reihung? selection sort: größtes Element an letzte Stelle, zweitgrößtes an zweitletzte Stelle, usw. einfach aber ineffizient! insertion sort: In absteigender Reihenfolge: das i-te Element in den sortierten Bereich [i+1, …, n] einsortieren noch ineffizienter!

3 Beispiele selectionSort insertionSort

4 Bubblesort Ineffizienz vorher: „weites“ Vertauschen mit Informationsverlust Idee: Tauschen von Nachbarn Falls zwei Nachbarn in verkehrter Reihenfolge, vertausche sie nach dem i-ten Durchlauf sind die obersten i Elemente sortiert package Sortieren; public class Sortieren { public static final int n = 5; static void printReihung(int reihung[]) { for (int i = 0; i<n; i++) System.out.print(reihung[i] + " "); System.out.println(""); } static void fillReihungRandom(int reihung[]) { final int range = 100; reihung[i]=(int) (Math.random()*range); static void swap (int[] a, int i, int j) { int h = a[i]; a[i] = a[j]; a[j] = h; } static void bubbleSort (int[] a) { for (int k=n-1; k>0; k--) { for(int i=0; i<k; i++) { if (a[i]>a[i+1]) { swap(a,i,i+1); printReihung(a); public static void main(String[] args) { int[]r=new int[n]; fillReihungRandom(r); printReihung(r); bubbleSort(r); static void bubbleSort (int[] a) { for (int k=n-1; k>0; k--) { for(int i=0; i<k; i++) { if (a[i]>a[i+1]) swap(a,i,i+1); } }

5

6 Quicksort berühmter, schneller Sortieralgorithmus
wähle ein „mittelgroßes“ Element w=a[k], alle kleineren nach links, alle größeren nach rechts rekursiv linke und rechte Teile sortieren public static void qSort(int[] a, int lo, int hi) { if (lo<hi) { int pivIndex = partition(a,lo,hi); qSort(a,lo,pivIndex-1); qSort(a, pivIndex+1, hi); } } public static void quickSort(int[] a) { qSort(a,0,n-1); } package Sortieren; public class Sortieren { public static final int n = 5; static void printReihung(int reihung[]) { for (int i = 0; i<n; i++) System.out.print(reihung[i] + " "); System.out.println(""); } static void fillReihungRandom(int reihung[]) { final int range = 100; reihung[i]=(int) (Math.random()*range); static void swap (int[] a, int i, int j) { int h = a[i]; a[i] = a[j]; a[j] = h; } private static int partition(int[]a, int lo, int hi) { swap(a,(lo+hi)/2, hi); int w = a[hi], k=lo; for (int i=k; i<hi; i++) if (a[i]<w) {swap(a,i,k); k++;} swap(a,k,hi); return k; public static void qSort(int[]a, int lo, int hi) { if (lo<hi) { int pivIndex = partition(a,lo,hi); qSort(a,lo,pivIndex-1); qSort(a, pivIndex+1, hi); public static void quickSort(int[] a) { qSort(a,0,n-1); public static void main(String[] args) { int[]r=new int[n]; fillReihungRandom(r); printReihung(r); quickSort(r);

7 Partitionierung private static int partition(int[]a, int lo, int hi) { swap(a,(lo+hi)/2, hi); int w = a[hi], k=lo; for (int i=k; i<hi; i++) if (a[i]<w) {swap(a,i,k); k++;} swap(a,k,hi); return k;} Idee: Pivotelement w irgendwo aus der Mitte wählen (eigentlich egal), am rechten Rand (hi) ablegen Dann 3 Bereiche bilden lo..k-1 : Elemente kleiner als w k..i-1: Elemente größer gleich w i..hi-1: unsortierte Elemente package Sortieren; public class Sortieren { public static final int n = 5; static void printReihung(int reihung[]) { for (int i = 0; i<n; i++) System.out.print(reihung[i] + " "); System.out.println(""); } static void fillReihungRandom(int reihung[]) { final int range = 100; reihung[i]=(int) (Math.random()*range); static void swap (int[] a, int i, int j) { int h = a[i]; a[i] = a[j]; a[j] = h; } private static int partition(int[]a, int lo, int hi) { swap(a,(lo+hi)/2, hi); int w = a[hi], k=lo; for (int i=k; i<hi; i++) if (a[i]<w) {swap(a,i,k); k++;} swap(a,k,hi); return k; public static void qSort(int[]a, int lo, int hi) { if (lo<hi) { int pivIndex = partition(a,lo,hi); qSort(a,lo,pivIndex-1); qSort(a, pivIndex+1, hi); public static void quickSort(int[] a) { qSort(a,0,n-1); public static void main(String[] args) { int[]r=new int[n]; fillReihungRandom(r); printReihung(r); quickSort(r);

8 9.3 Graphalgorithmen bereits behandelt: transitive Hüllenbildung (Warshall-Algorithmus) Heute: Tiefensuche, Breitensuche Starke Verbandskomponenten minimale Spannbäume aus: „Taschenbuch der Algorithmen“, erscheint demnächst (März 2008) Hrsg.: Vöcking, Alt, Dietzfelbinger u.a. Springer eXamen.press 400 S.

9 Tiefensuche Beispiel:
Gegeben ist ein Graph sowie ein Anfangsknoten im Graphen, gesucht ist irgendein Knoten mit einer bestimmten Eigenschaft. Besuche der Reihe nach alle Knoten, die über Kanten erreichbar sind Also: zunächst den ersten vom Anfangsknoten erreichbaren Knoten Dann: den ersten von diesem Knoten aus erreichbaren, und so weiter Wenn kein Knoten mehr erreichbar ist, kehre zum letzten Punkt zurück, an dem es noch weitere Kanten gab Wenn vom Anfangsknoten alle Kanten abgesucht wurden, ist der gesamte erreichbare Teil des Graphen abgesucht Beispiel: 1 2 8 3 6 9 4 5 7 10 11

10 Algorithmus B A E rekursiv! C D
„Markieren“ kann zum Beispiel dadurch geschehen, dass ein Sternchen oder eine fortlaufende Nummer dazugeschrieben wird. rekursiv! 1 prozedur Tiefensuche (Knoten x) 2  falls Ausgang erreicht dann stopp 3  sonst falls x unmarkiert dann 4  markiere x; 5  für alle Nachfolgerknoten y von x tue Tiefensuche(y)   

11 Ausführung B A E C D A Anfangsknoten; Kanten zu B und C
1. 2. 3. 4. 5. A Anfangsknoten; Kanten zu B und C B ist erster Nachfolger von A; Kante zu D D ist Nachfolger von B, Kante zu E E ist Nachfolger von D, Kante zu B B wurde schon markiert, Rückkehr zu E E hat keine weiteren Nachfolger, Rückkehr zu D D hat keine weiteren Nachfolger, Rückkehr zu B B hat keine weiteren Nachfolger, Rückkehr zu A C ist zweiter Nachfolger von A, Kante zu D D wurde schon markiert, Rückkehr zu C C hat keine weiteren Nachfolger, Rückkehr zu A A hat keine weiteren Nachfolger, Stopp

12 Tiefensuch-Baum Drei Arten von Kanten:
1. B 2. 3. D E 4. C 5. A B C D E 1. 2. 3. 4. 5. oder Drei Arten von Kanten: Vorwärtskanten, z.B. von A nach C Querkanten, z.B. von C nach D Rückwärtskanten, z.B. von E nach B In gerichteten Graphen bilden nur Rückwärtskanten Zyklen!

13 Zyklensuche Rückwärtskanten verweisen auf einen Knoten, der noch „in Bearbeitung“ ist Erweiterte Markierung „noch nicht begonnen“ (oder „unmarkiert“, am Anfang alle Knoten) „in Bearbeitung“ „abgeschlossen“ Wenn eine Kante zu einem Knoten „in Bearbeitung“ führt, wurde ein Zyklus gefunden 1 prozedur Zyklensuche (Knoten x) 2  falls Markierung(x) = „in Bearbeitung“ dann Zyklus gefunden 3  sonst falls Markierung(x) = „noch nicht begonnen“ dann 4  Markierung(x) := „in Bearbeitung“; 5  für alle Nachfolgerknoten y von x tue Zyklensuche(y); 6  Markierung(x) := „abgeschlossen“;

14 Aufrufbeispiel Fertig! Zyklensuche (A) // A noch nicht begonnen
A in Bearbeitung Zyklensuche (B) // B noch nicht begonnen B in Bearbeitung Zyklensuche (D) // D noch nicht begonnen D in Bearbeitung Zyklensuche (E) // E noch nicht begonnen E in Bearbeitung Zyklensuche (B) // B in Bearbeitung Zyklus gefunden! E abgeschlossen D abgeschlossen B abgeschlossen Zyklensuche (C) // C noch nicht begonnen C in Bearbeitung Zyklensuche (D) // D abgeschlossen C abgeschlossen A abgeschlossen A abgeschlossen in Bearbeitung in Bearbeitung B C abgeschlossen in Bearbeitung abgeschlossen D in Bearbeitung abgeschlossen abgeschlossen E in Bearbeitung Fertig!

15 Zyklen finden Was tun, wenn ein Zyklus entdeckt wird?
Um alle Knoten auf dem Zyklus auszugeben, muss man sich „merken“, welche gerade in Bearbeitung sind Zusätzliche Datenstruktur zum Speichern der Knoten „in Bearbeitung“ nötig Geeignet: Liste bzw. Stapel von Knoten 1 prozedur Zyklenfinden (Knoten x) 2  falls Markierung(x) = „in Bearbeitung“ dann 3  Zyklus gefunden; alle Knoten auf dem aktuellen Pfad ab x liegen auf dem Zyklus 4  sonst falls Markierung(x) = „noch nicht begonnen“ dann 5  Markierung(x) := „in Bearbeitung“; 6  Verlängere den aktuellen Suchpfad um x; 7  für alle Nachfolgerknoten y von x tue Zyklenfinden(y); 8  Markierung(x) := „abgeschlossen“; 9  Entferne x (das letzte Element) aus dem aktuellen Pfad;  

16 Ausgabe des Ergebnisses
 B, D, E gehören zum Zyklus aktueller Pfad: ABDE Kante von E führt zu B Programmieraufgabe: für ein gegebene Liste L von Knoten und eine Knotenbezeichnung k alle Elemente bis zum ersten Vorkommnis von k rückwärts ausgeben. Beispiel: Eingabe „ZYKLENSUCH“ und „E“, Ausgabe „HCUSNE“

17 Starke Zusammenhangskomponenten
ein Beispielgraph: Starke Zusammenhangskomponente: Verbundene Zyklen (jeder Knoten ist von jedem erreichbar) Alle Knoten in einer Zusammenhangskomponente sind sozusagen „äquivalent“ Quotientengraph: ersetze jede starke Zusammenhangskomponente durch einen eigenen Knoten ( zyklenfrei!) Tarjan‘s Algorithmus zur Berechnung des Quotientengraphen ist eine kleine Erweiterung von prozedur Zyklenfinden

18 Tarjan‘s Algorithmus

19 Vorbereitung Falls Zyklus gefunden, wird nichts direkt unternommen
Tiefensuchnummer definiert wie vorher; Komponentennummer wird die kleinste Tiefensuchnummer eines Knotens der Komponente

20 Hauptteil rekursiver Aufruf für alle Kinder des Knotens
Falls ein Kindknoten eine niedrigere Komponentennummer bekommen hat, wird sie übernommen

21 Nacharbeiten Beim rekursiven Aufstieg gilt: wenn sich die Komponentennummer nicht geändert hat, hat der Knoten die kleinste Tiefensuchnummer der Komponente Ausgabe der Komponenten: mit zusätzlichem Stapel

22 minimale Spannbäume Quotientengraph: Redundanz beseitigen durch „Zusammenfassen“ von Knoten zyklenfrei, d.h. endliche Halbordnung wie bekommt man aus Graph Baumstruktur? Spannbäume: Redundanz beseitigen durch „Löschen“ von Kanten gegeben: (ungerichteter, gewichteter) Graph gesucht: eine Teilmenge aller Kanten, die einen Baum bilden (also zyklen- bzw. kreisfrei), so dass alle Knoten erreichbar sind; (Summe der Kantengewichte minimal) Anwendung: z.B. Optimierung von Netzen

23 „lokaler“ Ansatz: Tiefen- oder Breitensuche
nicht geeignet zum Finden „optimaler“ Bäume „globale“ Ansätze: Kanten wegnehmen, bis der Graph zerfällt Kanten hinzufügen, bis Zyklen entstehen

24 Konstruktion eines Spannbaumes
gegeben zusammenhängender gerichteter Graph G=(V,E), gesucht Spannbaum G=(V,C) mit CE, G ist zusammenhängend, G ist Baum Kreis = Rückwärts- oder Querkante 1 prozedur Spannbaum (Graph G) 2 C:= empty(); 3 L := E 4 solange L nicht leer wähle irgendeine Kante e aus L L-= {e}; wenn e mit (V,C) keinen Kreis bildet dann C += {e} 9 Rückgabe (V,C)

25 Algorithmus von Kruskal
„Führe den folgenden Schritt so oft wie möglich aus: Wähle unter den noch nicht ausgewählten Kanten von G (dem Graphen) eine kürzeste Kante, die mit den schon gewählten Kanten keinen Kreis bildet“ 1 prozedur Kruskal (Graph G) 2  Sortiere die Kanten von G aufsteigend nach ihrem Kantengewicht. 3 C := empty(); 4 L := E 5 solange L nicht leer sei e Kante in L mit minimalem Kantengewicht L-= {e}; wenn e mit (V,C) keinen Kreis bildet dann C += {e} 10 Rückgabe M = (V,C) ist ein minimaler Spannbaum von G 

26 Benötigte Routinen Wählen der Kante mit kleinstem Gewicht
 Vorsortieren der Kanten! Test auf Kreisfreiheit  Union-Find-Struktur! Union-Find-Struktur: Repräsentation von Äquivalenzklassen Union: Vereinigt zwei Äquivalenzklassen Find: liefert zu beliebigem Element einen eindeutigen Repräsentanten der Äquivalenzklasse effiziente Implementierung mit Bäumen möglich! Demos unter

27 Union-Find bei Kruskal
Äquivalenzklassenpartition: alle Knoten die von einem gegebenen Knoten erreichbar sind oder von denen der Knoten erreichbar ist, liegen in der selben Partition (transitive Hülle der ungerichteten Kanten-Relation) initial: feinste Partitionierung, d.h. jeder Knoten bildet eine Partition Betrachtung der Kante k=(n1,n2): Wenn n1 und n2 in der selben Partition liegen (d.h. n1 erreicht n2 oder umgekehrt), entsteht durch k ein Kreis Wenn n1und n2 in verschiedenen Partitionen liegen, müssen diese bei Hinzunahme von k vereinigt werden


Herunterladen ppt "Praktische Informatik 1"

Ähnliche Präsentationen


Google-Anzeigen