Informatik A Zusammenfassung

Ähnliche Dokumente
Name: Seite 2. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Informatik II Prüfungsvorbereitungskurs

Algorithmen und Datenstrukturen. Bäume. M. Herpers, Y. Jung, P. Klingebiel

Name: Seite 2. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Name: Seite 1. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Name: Seite 1. Beantworten Sie die Fragen in den Aufgaben 1 und 2 mit einer kurzen, prägnanten Antwort.

Übung Algorithmen und Datenstrukturen

13. Bäume: effektives Suchen und Sortieren

13. Bäume: effektives Suchen und Sortieren

Programm heute. Algorithmen und Datenstrukturen (für ET/IT) Übersicht: Graphen. Definition: Ungerichteter Graph. Definition: Ungerichteter Graph

18. Natürliche Suchbäume

9. Natürliche Suchbäume

Datenstrukturen. Mariano Zelke. Sommersemester 2012

Suchen und Sortieren Sortieren. Heaps

Grundlagen. Name: Seite 2

Algorithmen und Datenstrukturen 2. Dynamische Datenstrukturen

Stud.-Nummer: Datenstrukturen & Algorithmen Seite 1

(a, b)-bäume / 1. Datenmenge ist so groß, dass sie auf der Festplatte abgespeichert werden muss.

7. Dynamische Datenstrukturen Bäume. Informatik II für Verkehrsingenieure

Teil VII. Hashverfahren

Übung Algorithmen und Datenstrukturen

Pro Informatik 2009: Objektorientierte Programmierung Tag 18. Marco Block-Berlitz, Miao Wang Freie Universität Berlin, Institut für Informatik

Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken.

7. Sortieren Lernziele. 7. Sortieren

Vorlesung Datenstrukturen

Informatik II Prüfungsvorbereitungskurs

Datenstrukturen und Algorithmen D-INFK

Datenstrukturen: Mathematische Grundlagen. 26. Juli / 27

EINI LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

Vorlesung Informatik 2 Algorithmen und Datenstrukturen

EINI LW. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 11/12

(Digital) Sorting. October 25, Algorithms & Datastructures 2 Exercises WS 2016

EINI LogWing/WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure. Vorlesung 2 SWS WS 17/18

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

Übung Algorithmen und Datenstrukturen

Komplexität eines Algorithmus, Grössenordnung, Landau-Symbole, Beispiel einer Komplexitätsberechnung (Mergesort) 7. KOMPLEXITÄT

NAME, VORNAME: Studiennummer: Matrikel:

Heapsort / 1 A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8]

Algorithmen und Datenstrukturen (für ET/IT)

Fragenkatalog 1. Kurseinheit

Informatik II, SS 2014

Informatik II. Woche 15, Giuseppe Accaputo

EINI LW/WiMa. Einführung in die Informatik für Naturwissenschaftler und Ingenieure Vorlesung 2 SWS WS 16/17

In C und Java müssen Variablen und Methodenergebnisse durch Typangaben erläutert werden. Welche der folgenden Aussagen sind korrekt und welche nicht:

16. Dynamische Datenstrukturen

Dr. Lars Hildebrand Fakultät für Informatik Technische Universität Dortmund

Teil 1: Suchen. Ausgeglichene Bäume B-Bäume Digitale Suchbäume. M.O.Franz, Oktober 2007 Algorithmen und Datenstrukturen - Binärbäume 1-1

Kapitel 10. Komplexität von Algorithmen und Sortieralgorithmen

Physikalisch Technische Lehranstalt Wedel 31. Januar 2004 Prof. Dr. Uwe Schmidt

Übung Algorithmen und Datenstrukturen

Bäume 1. Thomas Röfer

Informatik II, SS 2016

Graphdurchmusterung, Breiten- und Tiefensuche

Informatik II Vorlesung am D-BAUG der ETH Zürich

Stud.-Nummer: Datenstrukturen & Algorithmen Seite 1

Übung 4: Die generische Klasse AvlBaum in Java 1

Lernmodul 7 Algorithmus von Dijkstra

Keller, Schlangen und Listen. Elementare Datenstrukturen Keller, Schlangen und Listen 1 / 14

14. Sortieren II Heapsort. Heapsort. [Max-]Heap 7. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

Gliederung. 5. Compiler. 6. Sortieren und Suchen. 7. Graphen

f 1 (n) = log(n) + n 2 n 5 f 2 (n) = n 3 + n 2 f 3 (n) = log(n 2 ) f 4 (n) = n n f 5 (n) = (log(n)) 2

Algorithmen I. Tutorium 1-3. Sitzung. Dennis Felsing

Vorlesung Informatik 2 Algorithmen und Datenstrukturen

Datenstrukturen. Mariano Zelke. Sommersemester 2012

Punkte. Teil 1. Teil 2. Summe. 1. Zeigen Sie, dass der untenstehende Suchbaum die AVL-Bedingung verletzt und überführen Sie ihn in einen AVL-Baum.

Quicksort ist ein Divide-and-Conquer-Verfahren.

Inhaltsverzeichnis. Teil 1 Grundlagen 21. Teil 2 Datenstrukturen 85

Anwendungsbeispiel MinHeap

Universität München, Hans-Peter Kriegel und Thomas Seidl Informatik II a[0] a[1] a[2] a[3] a[n 1]

Übungsblatt 13. Abgabe / Besprechung in Absprache mit dem Tutor

Datenstrukturen Teil 2. Bäume. Definition. Definition. Definition. Bäume sind verallgemeinerte Listen. Sie sind weiter spezielle Graphen

Datenstrukturen und Algorithmen 2. Klausur SS 2001

Algorithmen und Datenstrukturen 12

11. Rekursion, Komplexität von Algorithmen

18. Natürliche Suchbäume

13. Hashing. AVL-Bäume: Frage: Suche, Minimum, Maximum, Nachfolger in O(log n) Einfügen, Löschen in O(log n)

13. Dynamische Datenstrukturen

Kapitel 12: Induktive

Fachhochschule Wedel 31. Januar 2004 Prof. Dr. Uwe Schmidt

Kapitel 9. Komplexität von Algorithmen und Sortieralgorithmen

Datenstrukturen und Algorithmen (SS 2013) Prof. Dr. Leif Kobbelt Thomas Ströder, Fabian Emmes, Sven Middelberg, Michael Kremer

Wiederholung. Bäume sind zyklenfrei. Rekursive Definition: Baum = Wurzelknoten + disjunkte Menge von Kindbäumen.

Übungen zu Algorithmen

7. Verkettete Strukturen: Listen

Schwerpunkte. Verkettete Listen. Verkettete Listen: 7. Verkettete Strukturen: Listen. Überblick und Grundprinzip. Vergleich: Arrays verkettete Listen

Übung 3 Musterlösung

Datenstrukturen und Algorithmen (SS 2013)

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps

Algorithmen und Datenstrukturen (Th. Ottmann und P. Widmayer) Folien: Suchverfahren Autor: Stefan Edelkamp / Sven Schuierer

Transkript:

Informatik A Zusammenfassung 1. Daten und Zahlen 2-er Komplement Komplexitätsklassen Variablen Konstantenbezeichner Rechnen mit Binärzahlen Gleitkommazahlen 2. Java Kontrollstrukturen Algorithmus Methode Obkektorientierte Programmierung Binden (statisch, dynamisch) 3. Endliche Automaten formale Definition Bsp.: Binärzahl durch 3 teilbar? 4. Rekursion Türme von Hanoi 5. Halteproblem 6. Sortieren Komplexität-Übersicht SelectionSort BubbleSort/ShakerSort MergeSort QuickSort BucketSort/RadixSort HeapSort Heap

7. Abstrakte Datentypen Liste Keller Schlange (binärer) Baum Suchbaum AVL-Baum Traversierungen Intervallinorder Mengen verwalten Spielbaum 8. Hashing Ofenes Hashing Geschlossenes Hashing Laufzeit 9. Graphen gerichteter/ungerichteter Graph Implementationen Adjazenzmatrizen Adjazenzlisten Typische Probleme für Graphen 10. Suchen Tiefensuche Breitensuche 11. Wichtige Algorithmen Traversieren, Hamiltonkreis, Traveling Salesman All-pairs-shortest-path, Single-source-shortest-path Topologisches Sortieren, Chinese Postman

Codierung ganze Zahlen im 2-er Komplement 0 1 1 1 7 0 1 1 0 6 0 1 0 1 5 0 1 0 0 4 0 0 1 1 3 0 0 1 0 2 0 0 0 1 1 0 0 0 0 0 1 1 1 1-1 1 1 1 0-2 1 1 0 1-3 1 1 0 0-4 1 0 1 1-5 1 0 1 0-6 1 0 0 1-7 1 0 0 0-8 Komplexitätsklassen: log n binäre Suche n lineare Suche n * log n schlaues Sortieren n 2 dummes Sortieren n 3 Gleihungssystem lösen 2 n alle Teilmengen n! alle Permutationen Variablen: Konstantenbezeichner Was sorgt für Speicherverwaltung? einfache Datentypen (float, char, int) Konstante Schlüsselwort final

Datentyp legt fest: Wertbereich Operationen Eingabe (char) in weiterverwendbare Zahlen (int) umwandeln: Jedem Zeichen ist ein ASCII-code zugewiesen Char c; (int) c liefert ASCII-Nummer in integer form Negative Zahl berechen: Gegeben x : -4 Finde +x : 0 1 0 0 Inverieren : 1 0 1 1 Addiere 1 : 1 1 0 0 Bei Addition: Überlauf beachten! Trick: Vorzeichenbit verdoppeln, müssen nach Addition identisch sein: 0 0 1 1 1 7 0 0 0 1 1 3 + 0 0 0 0 1 1 1 1 0 1 1-5 0 1 0 0 0 1 1 1 1 0-2 Ergebnis undefiniert Ergebnis ok!

[[ Gleitkommazahlen ]] Standart: float, double Darstellung: x = m * 2 e Verfahren: x = 13,5 = 1,6875 * 2 3 0, 6875 verdoppeln 1, 3750 verdoppeln 0, 7500 verdoppeln 1, 5000 verdoppeln 1, 0000 Reduzierte Mantisse: [1 0 1 1] = 0.6875 Exponent: [0 1 1] = 3 0 0 0 0 0 0 0 1 1 1 0 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 Vorzeichen Exponent Reduzierte Mantisse Multiplikation: Exponenten addieren Mantisse multiplizieren 12 * 20 = (1,5 * 2 3 ) * (1,25 * 2 4 ) = (1,5 * 1,25) * (2 3 * 2 4 ) = 1,875 * 2 7 = 240 Addition: Exponenten angleichen Mantisse addieren 12 + 20 = (1,5 * 2 3 ) + (1,25 * 2 4 ) = (0,75 * 2 4 ) + (1,25 * 2 4 ) = (0,75 + 1,25) * 2 4 = 32

JAVA Kontrollstrukturen: Regeln dynamischen Ablauf der Anweisungsfolge eines Programms durch Bedingungen, Verzweigungen und Schleifen Abzählreim: Algorithmus = endlich lange Vorschrift, bestehend aus Einzelanweisungen Häufig benutzte Algorithmen Methode (Klassen- oder Objektbezogen) Schlüsselwort static Klassenmethode Aufrufmechanismus: call-by-value

Objektorientierte Programmierung: Klasse class Hund() Objekt Hund hasso Konstruktor Hasso = new hund() Datenfelder Hasso.gewicht = 42 Vererbung class Schlittenhund extend Hund { } Überschreiben Überladen Methoden Hasso.sitz() Auf Konstruktor der Oberklasse zugreifen super() Binden: Wenn mehrere Methoden mit gleichem Namen und unterschiedlicher Parameterliste existieren, ist die Methode überladen. Statisches Binden bezeichnet den Vorgang, einem Objekt zur Übersetzungszeit den Programmcode fest zuzuordnen; dynamisches Binden bezeichnet den Vorgang, einem Objekt zur Laufzeit den Programmcode zuzuordnen. Referenzen modellieren Zeiger, Verweise

Endliche Automaten: 5-Tupel A = (S,, δ, s0, F) - S == endliche Zustandsmenge - == endliches Eingabealphabet - δ: S x S == Überführungsfunktion - s0 S == Startzustand - F S == Endzustände Typische Überführungsfunktion im Code: z = delta[z] [ (int) eingabe (int) 0 ] Beispiel: ist Binärzahl durch 3 teilbar?

Überführungsfunktion: Eingabe Zustände 0 1 r0 r0 r1 r1 r2 r0 r2 r1 r2 r0 ist Start und Zielzustand Java-Code Zustandüberführung mit einem Feld: Zustand: s Int [ ] [ ] delta = { (0,1), 0 (2,0), 1 (1,2) }; 2 Eingabe durchgehen: For (int i=0; i < zeile.length; i++) { Wende Überführungsfunktion an: s ist Zustand switch(zeile[i]) { case `0 : s = delta[s] [0]; break; case `1 : s = delta[s] [1]; break; default } Je nach dem ob also ne 0 oder 1 als Eingabe kommt gehe in unserem Feld in den jeweiligen Zustand (in die jeweilige Zeile) // delta[2] [0] 2. Reihe 0.te Spalte

[[ Suchen ]] Lineare Suche == Kompletter Durchlauf eines Arrays bis gefunden Worst case: O(n) Average case: O( n 2 ) Binäre Suche == Suche in geordneter Reihe, immer Mitte der noch zu durchsuchenden Reihe betrachten und entscheiden ob rechts oder links weitergesucht werden muss. Immer: O( log n ) Rekursion: Erneuter Aufruf einer Methode aus dem Methodenrumpf heraus Typischerweise werden dabei die aktuellen Parameter so modifiziert, dass die Problemgröße schrumpft, damit nach mehrmaligem Wiederholen dieses Prinzips schließlich kein weiterer Aufruf erforderlich ist und die Rekursion abbrechen kann. Jeder rekursive Algorithmus lässt sich auch iterativ implementieren

[[ Türme von Hanoi ]] n Scheiben mit abnehmender Größe liegen auf Startort A Sie sollen in derselben Reihenfolge auf Zielort C zu liegen kommen Die Regeln für den Transport lauten: 1.) Jede Scheibe muss einzeln transportiert werden 2.) Es darf nie eine größere Scheibe auf einer kleineren liegen 3.) Es darf ein Hilfsort B zum Zwischenlagern verwendet werden funktion bewege (Zahl i, Stab a, Stab b, Stab c) { falls (i > 0) { bewege(i-1, a, c, b); // n-1 von Start nach Zwischen verschiebe oberste Scheibe von a nach c; bewege(i-1, b, a, c); // n-1 Scheiben von Zwischen nach Ziel } } n-1 von Start nach Zwischen erste Scheibe von Start nach Ziel n-1 Scheiben von Zwischen nach Ziel Laufzeit: O(2 n 1) Beweis durch Induktion Induktionsverankerung: f(0) = 0 = 2 0 1 Induktionsschritt: Sei bis n 1 bewiesen: f(n) = 2 f(n 1) + 1 = 2 (2 n 1 1) + 1 = 2 n 2 + 1 = 2 n 1 Rekursionsgleichung Induktionsannahme

Halteproblem Beh.: Es gibt kein Programm, welches entscheidet, ob ein gegebenes Programm, angesetzt auf einen gegebenen Input, anhält. Beweis durchwiderspruch Annahme: Es gibt eine Methode haltetest in der Klasse Fee: public class Fee { public static boolean haltetest (char[]s, char[]t) { // liefert true, falls das durch die Zeichenkette s dargestellte // Java-Programm bei den durch die Zeichenkette t dargestellten // Eingabedaten anhaelt; // liefert false, sonst } } Dann lässt sich folgendes Java-Programm in der Datei Quer.java konstruieren: import AlgoTools.IO; public class Quer { public static void main(string[] argv) { char[] s = IO.readChars(); if (Fee.haltetest(s,s)) while (true); } } Sei q der String, der in der Datei Quer.java steht. Was passiert, wenn das Programm Quer.class auf den String q angesetzt wird? D.h. java Quer < Quer.java 1. Fall: Hält an haltetest(q,q) == false Quer angesetzt auf q hält nicht! 2. Fall: Hält nicht haltetest(q,q) == true Quer angesetzt auf q hält an! Also kann es die Methode haltetest nicht geben!

SORTIEREN Motivation für Sortieren: 1. Häufiges Suchen Einmal sortieren, dann jeweils log n Aufwand. 2. Tritt ein Element in zwei Listen L1, L2 auf? Sortiere L1 L2, dann nach Doppelten suchen! Eine Obere Schranke bezieht sich auf einen konkreten Algorithmus...wie lange dieser braucht um das Problem zu lösen Untere Schranke sagt aus wieviele Durchläufe jeder Algorithmus für ein Problem mindestens durchlaufen muss. Also eine untere Schranke heisst, es kann keinen Algorithmus geben, der das Problem in einer schnelleren Laufzeit lösen kann

O(n * log n ) ist untere Schranke für sortieren durch vergleichen, weil ein binärer Baum mit n! Blättern hat mindestens die Höhe n log n. 4 [[ SelectionSort ]] jeweils das kleinste nach vorne O(n 2 ) [[ BubbleSort ]] Jeweils unterschiedliche Paare vertauschen O(n 2 ) Variation: ShakerSort: einmal von vorne, einmal von hinten

[[ MergeSort ]] Divide&Conquer: sortiere 1. Hälfte, sortiere 2. Hälfte und vereinige Merge-Methode nimmt jeweils das kleinere aus beiden Mengen bis eine leer, dann Rest der anderen anhängen. O(n * log n) [[ QuickSort ]] Partitioniere die Folge in eine elementweise größere und eine elementweise kleinere O(n * log n)

Quicksort: im ungünstigsten Fall O(n 2 ) kann verhindert werden durch Bestimmung des Medians. (aber wenig sinnvoll) [[ BucketSort ]] Sortieren durch Verteilen auf einzelne Fächer (Buckets), Alphabet muss bekannt sein! O(n)

[[ RadixSort ]] Sortieren von Strings über endlichen Alphabet, durch mehrmaliges anwenden von BucketSort O(n)

[[ HeapSort ]] Benutze Heap und entferne immer wieder die Wurzel (kleinstes Element) bis leer Binärer Baum == entweder leer oder er besteht aus einem Knoten, dem 2 weitere Knoten zugeordnet sind Vater, Söhne, Wurzel, Blätter Heap == bis auf die letzte Ebene vollständiger binärer Baum, die einzelnen Knoten enthalten Schlüssel. Der Schlüssel eines Knotens ist stets kleiner als der seiner Söhne O(n * log n) Heap Implementation? Array

[[Heap]] Ein Heap ist ein binärer Baum (Konstruktion von Heap O(n)) Der kleinste Schlüssel bildet die Wurzel des Baumes und alle Nachfolger sind größer. Insert: neues Element an das Ende der Heaps Element, solange nach oben schieben bis es in der Wurzel steht oder der Schlüssel des Vaters kleiner als der des Elementes selbst ist. delete: Wurzel entfernen und an seine Stelle das am Ende des Heaps befindliche Element setzen. Element solange nach unten schieben, (mit kleinstem Schlüssel tauschen) bis es Blatt ist oder die Kinder größere Schlüssel als das Element selbst besitzen. get: einfach Schlüssel aus Wurzel holen. O(1) (nur Minimum!)

In welcher Reihenfolge werden die Elemente in dem Array gespeichert? der Breite nach Wurzel: Nummer 0 linker Sohn von Knoten i: 2*i +1 rechter Sohn von Knoten i: 2*i + 2 Welche Methoden sollte ein Interface Heap ankündigen? Object min( ) void delete( ) void insert(object) Im obigen Array implementiert...heapify durch tauschen im Array Kann man gut ein bestimmtes Element im Heap suchen oder herauslöschen? nein Wie wird der Heap aufgebaut? Warum ist Laufzeit hierfür O(n), obwohl eigentlich n mal mit Aufwand O(log n) repariert werden muss? mehr Knoten in unteren Ebenen [[ Externes Sortieren ]] Sortieren auf Medien mit sequentiellem Lese- und Schreibzugriff durch wiederholtes Mischen von bereits sortierten Folgen Lauf == monoton nicht fallende Teilfolge

ADT == Abstrakter Datentyp (Datenstruktur + Operationen) Interface == Schnittstelle, die nur abstrakte Methodenköpfe und Konstanten enthält, muss implementiert werden [[ Liste ]] Liste == Folge von Elementen mit einem sog. Aktuellen Element Operationen: empty( ) endpos( ) reset( ) advance( ) elem( ) insert(object x) delete ( ) Liefert true, falls leer Liefert true, wenn Liste abgearbeitet Das erste Listenelement wird zum aktuellen Der Nachfolger des akt. wird zum aktuellen Liefert das aktuelle Element Fügt vor das aktuelle Element ein Element ein; das neu eingefügte wird zum aktuellen Element Löscht das aktuelle Element

[[ Keller ]] Keller == Folge von Elementen mit einem sog. Top-Element (Last in First out) Operationen: empty( ) push(object x ) top( ) pop( ) Liefert true, falls Keller leer ist Legt Element auf Keller Liefert oberstes Element Entfernt oberstes Element

[[ Schlange ]] Schlange = Folge von Elementen mit einem sog. Front-Element (First in First out) O(log n)? Operationen: enq(object x ) deq( ) front( ) empty( ) Fügt x hinten ein Entfernt vorderstes Element Liefert vorderstes Element Liefert true, falls leer

[[ Baum ]] (binärer) Baum = ist entweder leer oder besteht aus einem Knoten, dem ein Element und 2 binäre Bäume (Söhne) zugeordnet sind Operationen: empty( ) left( ) right( ) value( ) Liefert true, falls Baum leer ist Liefert linken Teilbaum Liefert rechten Teilbaum Liefert Wurzelelement was implementieren Bäume? Menge Die Höhe eines Baumes hängt logarithmisch von de Anzahl seiner Elemente ab

[[ Suchbaum ]] (links < rechts) O(log n) Suchbaum Suchbaumoperationen: lookup(compareable x) insert(compareable x) delete(compareable x) sucht x in Menge liefert Comparable-Objekt falls gefunden liefert null sonst versucht x in Menge einzufügen liefert true, falls erfolgreich liefert false sonst versucht x aus Menge zu entfernen liefert true falls erfolgreich liefert false sonst public Comparable lookup(comparable x) Beginnt bei Wurzel Solange Knoten vorliegt Vergleiche x mit Knoteninhalt Dann je nach Vergleich entweder In linken Teilbaum oder rechten Teilbaum weitermachen

[[ AVL-Baum ]] (ausgeglichen) O(log n) AVL-Baum == ausgeglichener Suchbaum (Höhen seiner Söhne unterscheiden sich um höchstens 1) bal(x) = höherechts höhelinks Höhe eines AVL-baums ist 1,45 * log n also höchstebns 45% größer als erforderlich Einfügen: höchstens 1 Rotation Löschen: höchstens x Rotationen mit x = Anzahl der Knoten auf dem Weg zur Wurzel O(log n) Suchen: O(log n)

[[ Traversierungen ]] Rekursive Implementierungen inorder( knoten ): if knoten.links null then inorder( knoten.links ) print( knoten ) if knoten.rechts null then inorder( knoten.rechts ) preorder( knoten ): print( knoten ) if knoten.links null then preorder( knoten.links ) ) if knoten.rechts null then preorder( knoten.rechts postorder( knoten ): ) ) if knoten.links null then postorder( knoten.links if knoten.rechts null then postorder( knoten.rechts print( knoten ) Iterative Implementierung von Traversierungen mit Zuhilfenahme von Kellern

Intervallinorder: (abfangen) Intervall-inOrder( knoten ): if knoten.links null + if knoten.links > intervallanfang then inorder( knoten.links ) if knoten < intervallende { print( knoten ) } if knoten.rechts null then inorder( knoten.rechts ) Intervallpreorder Tiefensuche im Intervall // Preorder iterativ Tiefensuche...

Mengen verwalten Was für Sachen muss man den mit Daten so machen wenn man sie verwaltet? speichern, wiederfinden, löschen Angenommen, ein Kunde will die Implementation einer Menge, wie realisiere ich das? Hashing oder Suchbaum.

[[ Spielbaum ]] Spielbaum == Baum mit zwei Typen von Knoten: Minimum und Maximum Wert eines Blattes durch statische Stellungsbewertung Wert eines min-knotens: min der Söhne Wert eines max-knotens: max der Söhne Zur Implementation: der Baum ist nicht binär, daher hat jeder Knoten einen Verweis auf eine Liste von Söhnen

[[ Hashing ]] Offened Hashing == Einträge werden in einem Array von Buckets verwaltet, mehere Elemente können also den selben Hashwert belegen. Bei N Buckets und n Einträgen enthält jede Liste durchschnittlich n N Buckets

Geschlossenes Hashing == Beschränkte Anzahl von Plätzen Verwaltung durch ein Comparable[] inhalt und ein byte[] zustand verschiedene Sondierfunktionen zum Behandeln von Kollisionen Falls y = f(x) schon belegt ist, so suche für x einen Alternativplatz - Lineares Sondieren: y, y+1, y+2, y+3,... - Quadratisches Sondieren: y, y+1, y+4, y+9,... - Rehashing: y, y+f2(x),...

n = Anzahl der gespeicherten Objekte, N = Anzahl der Speicherpositionen, n N = α = Auslastungsfaktor Laufzeit: erfolglose Suche: 1 1 α = 5,0 (für α = 0,8) erfolgreiche Suche: ln (1 α) α = 2,01 (für α = 0,8) In 2 Schritten wird von 1.000.000 Elementen aus einer 1.250.000 großen Tabelle das richtige gefunden (AVL benötigt ezwa 20 Vergleiche) Bei höherem α steigt die Anzahl der Schritte stark an (exponentiell?)

[[ Graphen ]] Gerichteter Graph: G = (V,E) E V (Knotenmenge), V x V (Kantenmenge) Kanten sind einseitig Hier: V = {a,b,c,d} E = {(a,c),(a,b),(c,b),(c,d),(d,b),(b,d)} Ungerichteter Graph: G = (V,E) E V (Knotenmenge) P2(V) = 2-elementige Teilmenge von V Kanten können über eine Kostenfunktion gewichtet sein c: E {Reele Zahlen} Mit Graphen können binäre beziehungen zwischen Objekten modelliert werden. Die Objekte werden durch die Knoten, die Beziehungen durch die Kanten modelliert.

Implmentationsmöglichkeiten: (1) durch Adjazenzmatrizen: - Platzbedarf: O( V 2 ) - Zugriff auf einzelne Knoten in konstanter Zeit möglich - Kein effizientes Verarbeiten von Nachbaknoten - sinnvoll bei dicht besetzten Graphen und bei Algorithmen die wahlfreien Zugriff auf eine Kante benötigen Unbewertete Kanten: Bewertete kanten:

(2) durch Adjazenzlisten: - Platzbedarf: O( E ) - kein effizienter Zugriff auf Kanten möglich - sinnvoll bei dünn besetzten Graphen und bei Algorithmen die auf Nachbarn eines Knotens zugreifen müssen

[[ Typische Probleme für Graphen ]] Traversieren: jeden Knoten genau einmal besuchen (Hamilton-Path) All-pairs-shortest-path-Problem: günstigster Weg für jede Start-Ziel-Variante n x n Matrix in Polynomialzeit lösbar Multiplikation zweier n x n-matrizen O(n 3 ) oder hoch2,7 Single-source-shortest-path-Problem: Von einem bestimmeten Knoten kürzester Weg zu allen Knoten in Polynomialzeit lösbar Weg von a nach f: bestens 10 Sequenz: a b d c e f Laufzeit: O( E * log( V ) ) auf Grund von Heapsortierungen (Anwendung)

Hamilton-Kreis: Jeden Ort besuchen, Rückkehr an Ausgangsort Laufzeit: O(2 n ) Günstigster Hamilton-Kreis Travelling Salesman: Topologisches Sortieren: Nummerierung der Knoten, dass jeder Knoten eine Zahl {0,, n 1} erhält Suche f V {0,, n 1} mit f(x) < f(y) falls (x, y) E Laufzeit: O( E ) jeden Knoten einmal ansehen konstant Chinese Postman Jeden Weg (Kante) einmal ablaufen (Eulerweg) Laufzeit: O( n k )

[[ Tiefensuche ]] 1. Bestimme den Knoten an dem die Suche beginnen soll 2. Expandiere den Knoten und speichere alle Nachfolger in einem Keller 3. Rufe rekursiv für jeden der Knoten in dem Stack Tiefensuche auf o Falls der Keller leer sein sollte, tue nichts o Falls das gesuchte Element gefunden worden sein sollte, brich die Suche ab und liefere ein Ergebnis Tiefensuche im Intervall 1. Bestimme den Knoten, an dem die Suche beginnen soll, und bestimme die maximale Suchtiefe 2. Prüfe, ob der aktuelle Knoten innerhalb der maximalen Suchtiefe liegt o Falls nein: Tue nichts o Falls ja: 1. Expandiere den Knoten und speichere alle Nachfolger in einem Keller 2. Rufe rekursiv für jeden der Knoten des Keller Tiefensuche im Intervall auf und gehe zu Schritt 2 Tiefensuche auf Baum mittels Keller: 1. Baum in Keller 2. Baum aus Keller 3. Wurzel pop return 4. Rechter Sohn? Ja Keller 5. Linker Sohn? Ja 3. bis nichts mehr im Keller Laufzeit: entspricht preorder

[[ Breitensuche ]] 1. Bestimme den Knoten, an dem die Suche beginnen soll, und speichere ihn in einer Warteschlange ab. 2. Entnimm einen Knoten vom Beginn der Warteschlange und markiere ihn. o Falls das gesuchte Element gefunden wurde, brich die Suche ab o und liefere gefunden zurück. Anderenfalls hänge alle bisher unmarkierten Nachfolger dieses Knotens, die sich noch nicht in der Warteschlange befinden, ans Ende der Warteschlange an. 3. Wiederhole Schritt 2. 4. Wenn die Warteschlange leer ist, dann wurde jeder Knoten bereits untersucht. Beende die Suche und liefere nicht gefunden zurück. Laufzeit: Breitensuche auf einem Baum mit Hilfe einer Schlange 1. Baum in Schlange 2. Baum aus Schlange 3. Wurzel deq return 4. Linker Sohn? Ja Schlange 5. Rechter Sohn? Ja Schlange 6. Gehe zu 2. bis nichts mehr in Schlange Unterschied: Markieren mus nicht gemacht werden, da im Baum keine Schleifen möglich sind. Beliebiger Knotennachbar bei Graph

[[ wichtige Algorithmen ]] while (x!= 1) { if(x%2==0) x/=2; else x = x 3 + 1; counter++; } Collatz: // wenn x gerade: x = x 2 sonst: x = x 3 + 1 Fakultät: int fak = 1; for (i=1; i <= n; i++) fak *= i; rekursiv: static int fak(int n) { if(n==0) return 1; else return n * fak(n-1); } GGT while(y!=0) { z=x%y; x=y; y=z; } rekursiv static int ggt(int x, int y) { if(y==0) return x; else return gt(y,x%y); }

Dezimal Dual Positive ganze Zahlen: while(x!=0) { if(x%2==0) System.out.println( 0 ); else System.out.println( 1 ); x/=2; } obacht bits werden rückwärts generiert Mantisse: for(int i = 0; i<23; i++) { f*=2; if(f>=1) { System.out.println( 1 ); f--; } else System.out.println( 0 ); } Sieb des Eratosthenes int n = 1000 //willkürliche Obergrenze boolean[] sieb = new boolean[n]; for(int i=2; i<n; i++) sieb[i]=true; for(int i=2; i<n; i++) { if(sieb[i]) System.out.println(i); for(int j = i+1; j<n; j+=i) sieb[i]=false; //streiche alle Vielfachen der gefundenen Primzahl } }

Binäre Suche int[] a = {1,2,3,4,5,6,7,8,9}; int mitte, links, rechts; mitte = links = 0; rechts = a.length-1; while(links<=rechts) { mitte = (links + rechts) / 2; if(a[mitte]==x) break; //falls gefunden: fertig if(a[mitte]<x) links=mitte+1 //zu weit links? else rechts = mitte-1; //zu weit rechts? } //Sprung in die Mitte, weiter suchen links oder rechts. Dort wieder Sprung in die Mitte Fibonacci static int fib(int n) { if(n<=1) return 1; else return fib(n-1)+fib(n-2); } // 1 1 2 3 5 8 13