3.2 Algorithmen auf Listen und Bäumen

Größe: px
Ab Seite anzeigen:

Download "3.2 Algorithmen auf Listen und Bäumen"

Transkript

1 3.2 Algorithmen auf Listen und Bäumen Sortieren und Suchen sind elementare Aufgaben, die in den meisten Programmen anfallen. Verfahren zum Suchen und Sortieren spielen eine zentrale Rolle in der Algorithmik. Lernziele: - Intuitiver Algorithmusbegriff - Kenntnis wichtiger/klassischer Algorithmen und Algorithmenklassen - Zusammenhang Algorithmus und Datenstruktur - Wege vom Problem zum Algorithmus - Implementierungstechniken für Datenstrukturen und Algorithmen (vom Algorithmus zum Programm) Wir führen in den Bereich Algorithmen und Datenstrukturen ausgeh vom Problem ein. Andere Möglichkeit wäre gemäß der benutzten Datenstrukturen (Listen, Bäume, etc.). Übersicht über 3.2: Sortieren Suchen Sortieren Sortieren ist eine Standardaufgabe, die Teil vieler speziellerer, umfasserer Aufgaben ist. Untersuchungen zeigen, dass mehr als ein Viertel der kommerziell verbrauchten Rechenzeit auf Sortiervorgänge entfällt [Ottmann, Widmayer: Algorithmen und Datenstrukturen, Kap. 2]. Begriffsklärung: (Sortierproblem) Gegeben ist eine Folge s,..., s von sogenannten 1 N Datensätzen. Jeder Satz s i hat einen Schlüssel k i. Wir gehen davon aus, dass die Schlüssel ganzzahlig sind. Aufgabe des Sortierproblems ist es, eine Permutation π zu finden, so dass die Umordnung der Sätze gemäß π folge Reihenfolge auf den Schlüsseln ergibt: k k... k π(1) π(2) π(n) Offene Aspekte der Formulierung des Sortierproblem: - Was heißt, eine Folge ist gegeben? - Ist der Bereich der Schlüssel bekannt? - Welche Operationen stehen zur Verfügung, um π zu bestimmen? - Was genau heißt Umordnung? Wir betrachten: Sortieren durch Auswahl (engl. selection sort) Sortieren durch Einfügen (engl. insertion sort) Bubblesort Sortieren durch rekursives Teilen (quick sort) Sortieren durch Mischen (merge sort) Heapsort Aufgabenstellung: Wir benutzen Datensätze folgen Typs type dataset = int * string mit Vergleichsoperator: infix 4 leq fun op leq((kx:int,dx),(ky:int,dy))= (kx<=ky) Entwickle eine Funktion sort: dataset list dataset list so dass sort(xl) für alle Eingaben xl aufsteig sortiert ist. Insbesondere sind mehrfach Einträge und mehrere Einträge mit gleichem Schlüssel nicht ausgeschlossen. Sortieren durch Auswahl (selection sort) Algorithmische Idee: Entferne einen minimalen Eintrag min aus der Liste. Sortiere die Liste, aus der min entfernt wurde. Füge min als ersten Element an die sortierte Liste an

2 (* select: Hilfsfunktion liefert einen minimalen Eintrag der Liste bzw. x, falls x minimal. *) fun select x nil = x select x (y::yl) = if x leq y then select x yl else select y yl; (* delete: Hilfsfunktion löscht ein Vorkommen von x aus der Liste.*) fun delete x nil = nil delete x (y::yl) = if (x = y) then yl else y :: delete x yl; (* selectionsort: sortiert Liste min: ein minimaler Eintrag in Liste xl. rest: die Liste xl ohne min *) fun selectionsort nil = nil selectionsort (x::xl) = let val min = select x xl; val rest = delete min (x::xl); in min :: (selectionsort rest) Sortieren durch Einfügen (insertion sort) Algorithmische Idee: Sortiere zunächst den Rest der Liste. Füge dann den ersten Eintrag in die sortierte Liste ein. (* insert: Hilfsfunktion fügt Argument in sortierte Liste ein *) fun insert a nil = [a] insert a (y::yl) = if (a leq y) then a :: (y :: yl) else y :: (insert a yl) (* insertionsort: sortiert Liste *) fun insertionsort nil = nil insertionsort (x::xl) = insert x (insertionsort xl) Bubblesort Algorithmische Idee: Schiebe einen Eintrag nach rechts heraus: - Beginne dazu mit dem ersten Eintrag e. - Wenn schieben von e auf einen gleichen oder größeren Eintrag y stößt, schiebe y weiter. - Ergebnis: maximaler Eintrag max und Liste ohne max Sortiere die Liste ohne max und hänge max an. (* bubble: Hilfsfunktion liefert einen maximalen Eintrag der Liste und die Liste ohne den maximalen Eintrag *) fun bubble rl e nil = (rl,e) bubble rl e (y::yl) = if (e leq y) then bubble (rl@[e]) y yl else bubble (rl@[y]) e yl (* bubblesort: sortiert Liste *) fun bubblesort nil = nil bubblesort (x::xl) = let val (rl,max) = bubble nil x xl in (bubblesort rl)@[max] Quicksort: Sortieren durch Teilen Algorithmische Idee: Wähle einen beliebigen Datensatz mit Schlüssel k aus, das sogenannte Pivotelement. Teile die Liste in zwei Teile: - 1. Teil enthält alle Datensätze mit Schlüsseln < k - 2. Teil enthält die Datensätze mit Schlüsseln k We quicksort rekursiv auf die Teillisten an. Hänge die resultieren Listen und das Pivotelement zusammen. fun split p nil = (nil,nil) split p (x::xr) = let val (below, above) = split p xr in if p leq x then (below,x::above) else (x::below,above) fun qsort nil = nil qsort (p::rest) = let val (below,above) = split p rest in (qsort (qsort above)

3 Quicksort ist ein typischer Algorithmus gemäß der Divide-and-Conquer-Strategie: - Zerlege das Problem in Teilprobleme. - We den Algorithmus auf die Teilprobleme an. - Füge die Ergebnisse zusammen. Sortieren durch Mischen: Algorithmische Idee: Hat die Liste mehr als ein Element, berechne die Länge der Liste div 2 (halfsize). Teile die Liste in zwei Teile der Länge halfsize (+1). Sortiere die Teile. Mische die Teile zusammen. Mergesort ist auch effizient für das Sortieren von Datensätzen, die auf externen Speichermedien liegen und nicht vollständig in den Hauptspeicher geladen werden können. open List; fun merge nil nil = nil merge nil yl = yl merge xl nil = xl merge (x::xl) (y::yl) = if (x leq y) then x :: (merge xl (y::yl)) else y :: (merge (x::xl) yl); (* mergesort: sortiert gegebene Liste halfsize: Hälfte der Listenlänge. front: Vordere Hälfte der Liste. back : Hintere Hälfte der Liste. *) fun mergesort nil = nil mergesort (x::nil) = [x] mergesort xl = let val halfsize = (length xl) div 2; val front = take (xl,halfsize); val back = drop (xl,halfsize); in (* Merge 2 sortierte Listen! *) merge (mergesort front) (mergesort back) Heapsort Heapsort verfeinert die Idee des Sortierens durch Auswahl: Minimum bzw. Maximum wird nicht durch lineare Suche gefunden, sondern mit logarithmischem Aufwand durch Verwung einer besonderen Datenstruktur, dem sogenannten Heap. Algorithmische Idee: 1. Schritt: Erstelle den Heap zur Eingabeliste. 2. Schritt: - Entferne Maximumelement aus Heap (konstanter Aufwand) und hänge es an die Ausgabeliste. - Stelle Heap-Bedingung wieder her (logarithmischer Aufwand). - Fahre mit Schritt 2 fort bis der Heap leer. Ziele des Vorgehens: - Beispiel für komplexe, abstrakte Datenstruktur - Zusammenhang der algorithmischen Idee und der Datenstruktur. Der Begriff Heap ist in der Informatik überladen. Auch der Speicher für zur Laufzeit angelegte Variablen wird im Englischen heap genannt. Begriffsklärung: (zu Bäumen) Ein Baum heißt markiert, wenn jeder Knoten eine Markierung besitzt. Im Zusammenhang dieses Kapitels sind Markierungen Datensätze. Die Höhe eines Baumes ist der maximale Abstand eines Blattes von der Wurzel; die Höhe eines Baumes, der nur aus einem Blatt besteht, ist 1; die Höhe des leeren Baums ist 0. Die Tiefe eines Knotens ist sein Abstand zur Wurzel. Die Knoten gleicher Tiefe t nennt man das Niveau t. Ein Binärbaum ist ein Baum, in dem jeder Knoten keinen oder einen linken oder einen rechten oder einen linken und rechten Unterbaum besitzt. Die Größe eines Baums ist die Anzahl seiner Knoten. Ein Baum der Größe n heißt indiziert, wenn man seine Knoten mittels der Indizes 0,...,n-1 ansprechen kann. Ein Binärbaum heißt strikt, wenn jeder Knoten ein Blatt ist oder zwei Unterbäume besitzt

4 Ein Binärbaum der Höhe h heißt vollständig, wenn er strikt ist und alle Blätter die Tiefe h haben. Ein Binärbaum der Höhe h heißt fast vollständig, wenn - jedes Blatt die Tiefe h oder h-1 hat, - für die Knoten K des Niveaus h-1 gilt: 1. Hat K 2 Kinder, dann auch alle linken Nachbarn von K. 2. Hat K keine Kinder, dann sind auch alle rechten Nachbarn von K kinderlos. 3. Es gibt maximal ein K mit genau einem Kind, und dies ist links. Beispiel: (Fast vollständiger indizierter und markierter Binärbaum) 0: : 2 2: 3: 31 4: 42 5: Signatur für fast vollständige, markierte, indizierte Binärbäume: signature FVBINTREE = sig (* Typ fast vollständiger Binärbäume, ggf. leer *) type fvbintree; (* Erzeugt fast vollständigen Binärbaum, wobei die Listenelemente zu Markierungen werden *) val create : dataset list -> fvbintree; (* Anzahl der Knoten des Baums *) val size : fvbintree -> int ; (* Markierung am Knoten mit Index i *) val get : fvbintree * int -> dataset ; (* Vertausche Markierungen der Knoten mit Ind. i,,j *) val swap : fvbintree * int * int -> fvbintree; (* Entferne letzten Knoten *) val removelast: fvbintree -> fvbintree ; (* Knoten mit Index i hat linkes Kind *) val hasleft : fvbintree * int -> bool ; (* Knoten mit Index i hat rechtes Kind *) val hasright : fvbintree * int -> bool (* Index des linken Kinds von Knoten mit Index i *) val left : fvbintree * int -> int ; (* Index des rechten Kinds von Knoten mit Index i *) val right : fvbintree * int -> int 171 Vorgehen: Wir gehen zunächst davon aus, dass wir eine Datenstruktur zur Signatur FVBINTREE hätten und realisieren heapsort damit; d.h. ohne die Struktur/Implementierung zu kennen. Wir liefern dann eine effiziente Implementierung der Signatur. Im Zusammenhang mit der objektorientierten Programmierung werden wir die Implementierung weiter verfeinern. Wir benutzen die Datenstruktur ohne die Implementierung zu kennen; man sagt die Datenstruktur ist für den Nutzer abstrakt und spricht von abstrakter Datenstruktur. Die Signatur beschreibt die Schnittstelle der abstrakten Datenstruktur. Die Benutzung von Schnittstellen abstrakter Datenstrukturen ist ein zentraler Bestandteil der SW-Entwicklung. Eine abstrakte Datenstruktur kann unterschiedliche Implementierungen haben. Implementierungen können ausgetauscht werden, ohne dass der Nutzer seine Programme ändern muss! Begriffsklärung: (Heap) Ein markierter, fast vollständiger, indizierter Binärbaum mit n Knoten heißt ein Heap der Größe n, wenn die folge Heap-Eigenschaft erfüllt ist: Ist M ein Knoten und N ein Kind von M mit Markierungen k und k, dann gilt: M N k k. M N Bei einem Heap sind die Knoten entsprech einem Breiturchlauf indiziert (siehe Beispiel unten). Beispiel: (Heap) Heap der Größe 8: 7: 88 1: 62 2: 57 3: 31 4: 42 5: 51 6: 10 0:

5 Die Heap-Eigenschaft garantiert, dass der Schlüssel eines Knotens M größer gleich aller Schlüssel in den Unterbäumen von M ist. Insbesondere steht in der Wurzel ein Element mit einem maximalen Schlüssel. Beispiel: (Versickern lassen) 0: 18 1: 62 2: 57 Herstellen der Heap-Eigenschaft: 3: 10 4: 42 5: 51 Sei ein markierter, fast vollständiger Binärbaum gegeben, der die Heap-Eigenschaft nur an der Wurzel verletzt. 0: 62 Die Heap-Eigenschaft kann hergestellt werden, indem man den Wurzelknoten M rekursiv in dem Unterbaum mit dem größeren Schlüssel versickern lässt: - Gibt es kein Kind, ist nichts zu tun. - Gibt es genau ein Kind N, dann ist dies links und kinderlos: Ist k M < k N, vertausche die Markierungen. - Gibt es zwei Kinder und ist N das Kind mit dem größeren Schlüssel: Ist k M < k N, vertausche die Markierungen und fahre rekursiv mit dem Unterbaum zu N fort. 1: 18 2: 3: 10 4: 42 5: 51 0: 62 1: 42 2: 3: 10 4: 18 5: Funktion heapify formuliert auf Basis von FVBINREE: (* Annahme: Die Kinder von ix in b erfüllen die Heap-Eigenschaft *) fun heapify b ix = let val ds = get(b,ix) in if hasleft(b,ix) andalso not (hasright(b,ix)) then let val lx = left(b,ix) in if get(b,lx) leq ds then b else swap(b,ix,lx) else if hasright(b,ix) then let val lx = left(b,ix) ; val rx = right(b,ix); (* zu betrachtes Kind *) val cx = if get(b,lx) leq get(b,rx) then rx else lx in if get(b,cx) leq ds then b else heapify (swap(b,ix,cx)) cx else b Konkretisierung des Heapsort-Algorithmus: 1. Schritt: - Erzeuge Binärbaum-Repräsentation aus Eingabefolge. - Stelle Heap-Eigenschaft her, indem heapify ausgeh von den Blättern für jeden Knoten aufgerufen wird. Es reicht, nur Knoten mit Kindern zu berücksichtigen. 2. Schritt:: - Schreibe den Wurzel-Datensatz in die Ausgabe. - Schreibe den Datensatz des letzten Elementes in den Wurzelknoten. - Entferne das letzte Element. - Stelle die Heap-Eigenschaft wieder her. - Fahre mit Schritt 2 fort, solange die Größe > 0. Lemma: In einem fast vollständigen Binärbaum der Größe n sind die Knoten mit den Indizes (n div 2) bis n-1 Blätter

6 Heapsort: Abstrakte Version Wir betrachten zunächst Heapsort auf Basis des abstrakten Datentyps mit Signatur FVBINTREE: (* Hilfsfunktion für Schritt 1 *) fun heapifyall b = hpfyemb b ((size b) div 2) and hpfyemb b 0 = if size b = 0 then b else heapify b 0 hpfyemb b ix = hpfyemb (heapify b ix) (ix-1) (* heapsort: sortiert gegebene Liste *) fun heapsort xl = rev (sortheap (heapifyall (create xl))) and sortheap hp = if size hp = 0 then [] else let val maxds = get(hp,0) ; val hp1 = swap(hp,0,(size hp)-1); val hp2 = removelast hp1 ; val hp3 = heapify hp2 0 in maxds::(sortheap hp3) Heapsort profitiert davon, dass sich fast vollständige, markierte, indizierte Binärbäume sehr effizient mit Feldern realisieren lassen: Einschub: Felder Felder sind ein imperatives Sprachelement. Wir betrachten sie vor allem in Kapitel 4 und 5. Hier soll gezeigt werden, - wie Heaps effizient realisiert werden können. - dass auch in funktionalen Sprachen imperativ programmiert werden kann Begriffsklärung: (Variable) Eine Speichervariable oder einfach nur Variable ist ein Speicher/Behälter für Werte. Charakteristische Operationen auf einer Variablen v: - Zuweisen eines Werts w an v; - Lesen des Wertes, den v enthält/speichert/hat. Der Zustand einer Variablen v ist undefiniert, wenn ihr noch kein Wert zugewiesen wurde; andernfalls ist der Zustand von v durch den gespeicherten Wert charakterisiert. Variablen stellen wir graphisch durch Rechtecke dar: v: true v1: 7 v enthält/speichert den Wert true v1 enthält/speichert den Wert Begriffsklärung: (eindimensionale Felder) Ein Feld (engl. Array) ist ein n-tupel von Variablen des gleichen Typs T. Die Variablen des Tupels nennt man die Komponenten des Felds, T den Komponententyp. Die Komponenten sind in ML und Java von 0 bis n-1 durchnummeriert. Array: Eine Datenstruktur mit Modifikation ML stellt standardmäßig eine Datenstruktur für Felder bereit, die bzgl. des Elementtyps parametrisiert sind. Typen: Ist t ein ML-Typ, dann bezeichnet t array den Typ der Felder mit Elementen aus t Funktionen (Auszug): (* Erklärungen: siehe unten *) array : int * t t array (* Konstruktor *) fromlist: t list t array (* Konstruktor *) length : t array int (* les *) sub : t array * int t (* les *) update : t array * int * t unit (* schreib/modifizier *) Erklärung: array (n,x) erzeugt neues Feld mit n Komponenten; jede Komponente wird mit x initialisiert. fromlist xl erzeugt neues Feld mit n Komponenten, wobei n die Länge der Liste xl ist; die Komponenten werden mit den Listenelementen initialisiert. length ar liefert die Anzahl der Feldkomponenten. sub (ar,i) liefert den Wert, der in der i-ten Komponente von ar gespeichert ist. update (ar,i,x) speichert den Wert x an die i-te Komponente von ar. Dabei wird ar verändert!! Ergebnis ist der Wert (). Beispiel: (Modifikation in Feldern) > val a = fromlist [1,2,3]; val a = fromlist[1, 2, 3] : int Array.array > update (a,0,7); val it = () : unit > a; val it = fromlist[7, 2, 3] : int Array.array > val b = a; val b = fromlist[7, 2, 3] : int Array.array > update (a,1,8); val it = () : unit > b; val it = fromlist[7, 8, 3] : int Array.array

7 Realisierung von Heaps mit Feldern: Beispiel: (Heaps in Feldern) 7: 88 1: 62 2: 57 3: 31 4: 42 5: 51 6: 10 0: 88 1: 62 2: 57 3: 31 4: 42 5: 51 6: 25 7: 10 0: Beachte: 25 Ist ix der Index eines Knotens, dann ist: - 2*(ix+1)-1 der Index des linken - 2*(ix+1) der Index des rechten Kindes. structure FvBinTree : FVBINTREE = struct open Array; (* Typ fast vollständiger Binärbäume, ggf. leer. Implementiert mit Feldern; erste Komponente: genutzte Größe *) type fvbintree = int * (dataset array); (* fromlist: a list -> a array *) fun create xl =(List.length xl,fromlist xl); fun size (s,fbt) = s; fun get ((s,fbt),i) = sub(fbt,i); (* swap: Modifiziert fbt *) fun swap ((s,fbt),i,j) = let val tmp = sub(fbt,i) in update(fbt,i,sub(fbt,j)); update(fbt,j,tmp); (s,fbt) fun removelast (s,fbt) = (s-1,fbt) fun left ((s,fbt),i) = 2*(i+1)-1 ; fun right ((s,fbt),i) = 2*(i+1) ; fun hasleft((s,fbt),i) = (left((s,fbt),i)) < s fun hasright((s,fbt),i)= (right((s,fbt),i)) < s open FvBinTree; Abschließe Bemerkungen zu Es hätte klar werden müssen: Zu einem algorithmischen Problem (hier Sortieren) gibt es im Allg. viele Lösungen. Lösungen unterscheiden sich in: - der Laufzeiteffizienz (messbar) - der Speichereffizienz (messbar) - der Komplexität der Verfahrensidee (im Allg. nicht messbar). In den folgen Kapiteln werden wir demonstrieren, wie einige der obigen Algorithmen in anderen Sprachenparadigmen formuliert werden können; wie der Effizienz/Komplexitätsbegriff präzisiert werden kann Suchen Die Verwaltung von Datensätzen basiert auf drei grundlegen Operationen: - Einfügen eines Datensatzes in eine Menge von Datensätzen; - Suchen eines Datensatzes mit Schlüssel k; - Löschen eines Datensatzes mit Schlüssel k. Weitere oft gewünschte Operationen sind: sortierte Ausgabe, Suchen aller Datensätze mit bestimmten Eigenschaften, bearbeiten von Daten ohne eindeutige Schlüssel, etc. Entsprech unseren Datensätzen betrachten wir die folge Signatur / Schnittstelle: signature DICTIONARY = sig type dict; val Empty: dict; val get : dict * int -> bool * string ; val put : dict * int * string -> dict ; val remove: dict * int -> dict; In der Literatur zur funktionalen Programmierung wir get oft lookup oder search, put oft insert und remove oft delete genannt. Um den Zusammenhang zu OO-Schnittstellen augenfälliger zu machen, benutzen wir die dort üblichen Namen. Ziel ist es, Datenstrukturen zu finden, bei denen der Aufwand für obige Operationen gering ist. Wir betrachten hier die folgen Dictionary-Realisierungen: lineare Datenstrukturen (Übung) (natürliche) binäre Suchbäume (Vorlesung)

8 Binäre Suchbäume Begriffsklärung: (binärer Suchbaum) Ein markierter Binärbaum B ist ein natürlicher binärer Suchbaum (kurz: binärer Suchbaum), wenn die Suchbaum-Eigenschaft gilt, d.h. wenn für jeden Knoten K in B gilt: - Alle Schlüssel im linken Unterbaum von K sind echt kleiner als der Schlüssel von K. - Alle Schlüssel im rechten Unterbaum von K sind echt größer als der Schlüssel von K. Natürlich bezieht sich auf das Entstehen der Bäume in Abhängigkeit von der Reihenfolge der Einfüge-Operationen (Abgrenzung zu balancierten Bäumen). In einem binären Suchbaum gibt es zu einem Schlüssel maximal einen Knoten mit entsprecher Markierung. Datenstruktur: Wir stellen Dictionaries als Binärbäume mit Markierungen vom Typ dataset dar: datatype btree = Node of dataset * btree * btree Empty ; Die Konstante Empty repräsentiert das leere Dictionary. Binärbäume, die als Dictionary verwet werden, müssen die Suchbaum-Eigenschaft erfüllen. Alle Funktionen, die Dictionaries als Parameter bekommen, gehen davon aus, dass die Suchbaum-Eigenschaft für die Parameter gilt. Die Funktionen müssen garantieren, dass die Eigenschaft auch für Ergebnisse gilt. Man sagt: Die Suchbaum-Eigenschaft ist eine Datenstrukturinvariante von Dictionaries. Wir guarantieren die Datenstrukturinvariante u.a. dadurch, dass wir Nutzern der Datenstruktur keinen Zugriff auf den Konstruktor Node geben structure Dictionary : DICTIONARY = struct datatype btree = Node of dataset * btree * btree Empty ; type dict = btree ; fun get... (* siehe unten *) fun put... (* siehe unten *) fun remove... (* siehe unten *) Die Struktur Dictionary stellt nur die in der Signatur DICTIONARY vereinbarten Typen, Werte und Funktionen den Nutzern zur Verfügung. Einfügen: Algorithmisches Vorgehen: - Neue Knoten werden immer als Blätter eingefügt. - Die Position des Blattes wird durch den Schlüssel des neuen Eintrags festgelegt. - Beim Aufbau eines Baumes ergibt der erste Eintrag die Wurzel. - Ein Knoten wird in den linken Unterbaum der Wurzel eingefügt, wenn sein Schlüssel kleiner ist als der Schlüssel der Wurzel; in den rechten, wenn er größer ist. Dieses Verfahren wird rekursiv fortgesetzt, bis die Einfügeposition bestimmt ist. Insbesondere sind Node und btree nur in Dictionary verfügbar und nicht für Nutzer von Dictionary. Beispiel: Suchen eines Eintrags: Einfügen von 33: 45 Wenn kein Eintrag zum Schlüssel existiert, liefere (false, ) ; sonst liefere (true,s), wobei s der String zum Schlüssel ist: fun get (Empty, k) = (false,"") get (Node ((km,s),l,r),k) = if k < km then get (l,k) else if k > km then get (r,k) else (* k = km *) (true,s)

9 Die algorithmische Idee lässt sich direkt umsetzen. Beachte aber, dass das Dictionary nicht verändert wird, sondern ein neues erzeugt und abgeliefert wird: fun put (Empty,k,s) = Node((k,s),Empty,Empty) put (Node ((km,sm),l,r),k,s) = if k < km then Node ((km,sm),put(l,k,s),r) else if k > km then Node ((km,sm),l,put(r,k,s) else (* k = km *) Node ((k,s),l,r) Es gibt sehr viele Möglichkeiten, aus einer vorgegebenen Schlüsselmenge einen binären Suchbaum zu erzeugen. Bei sortierter Einfügereihenfolge entartet der binäre Suchbaum zur linearen Liste. Der Algorithmus zum Einfügen ist schnell, insbesondere weil keine Ausgleichs- oder Reorganisationsoperationen vorgenommen werden müssen. Bemerkungen: Die Reihenfolge des Einfügens bestimmt das Aussehen des binären Suchbaums: Reihenfolgen: 2 ; 3 ; 1 1 ; 3 ; 2 1 ; 2 ; 3 Löschen: Löschen ist die schwierigste Operation, da - ggf. innere Knoten entfernt werden und dabei - die Suchbaum-Eigenschaft erhalten werden muss Algorithmisches Vorgehen: Die Position eines zu löschen Knotens K mit Schlüssel X wird nach dem gleichen Verfahren wie beim Suchen eines Knotens bestimmt. - Dann sind drei Fälle zu unterscheiden: Fall: K ist ein Blatt. Lösche K: X Y Z Entsprech, wenn X in rechtem Unterbaum. 2. Fall: K hat genau einen Unterbaum. K wird im Eltern-Knoten durch sein Kind ersetzt und gelöscht: Y Z 3. Fall: K hat genau zwei Unterbäume. Problem: Wo werden die beiden Unterbäume nach dem Löschen eingehängt? Hier gibt es 2 symmetrische Lösungsvarianten: - Ermittle den Knoten KR mit dem kleinsten Schlüssel im rechten Unterbaum, Schlüssel von KR sei XR. - Speichere XR und die Daten von KR in K. - Lösche KR gemäß Vorgehen zu Fall 1 bzw. 2. (andere Variante: größten Schlüssel im rechten UB) Y Y X XR X Z Y Z Y Z Z XR Die anderen links-rechts-varianten entsprech

10 Umsetzung in ML: Die Fälle 1 und 2 lassen sich direkt behandeln. Für Fall 3 realisiere Hilfsfunktion removemin, die - nichtleeren binären Suchbaum b als Parameter nimmt; - ein Paar (min,br) als Ergebnis liefert, wobei -- min der kleinste Datensatz in b ist und -- br der Baum ist, der sich durch Löschen von min aus b ergibt. fun removemin (Node (d,empty,r)) = (d,r) removemin (Node (d,l,r)) = let val (min,ll) = removemin l; in (min, Node(d,ll,r)) fun remove (Empty,k) = Empty remove (Node((km,s),l,r),k)= if k < km then Node ((km,s), remove(l,k), r) else if k > km then Node ((km,s), l, remove(r,k)) else (* k = km *) case (l,r) of (Empty,rt) => r (lt,empty) => l (lt,rt) => let val (min,rr) = removemin r in Node (min,l,rr) 194 Diskussion: Der Aufwand für die Grundoperationen Einfügen, Suchen und Löschen eines Knotens ist proportional zur Tiefe des Knotens, bei dem die Operation ausgeführt wird. Ist h die Höhe des Suchbaumes, ist der Aufwand der Grundoperationen im ungünstigsten Fall also O(h), wobei log (N+1)-1 h N-1 für Knotenanzahl N. Folgerung: Bei degenerierten natürlichen Suchbäumen kann linearer Aufwand für alle Grundoperationen entstehen. Im ungünstigsten Fall ist das Laufzeitverhalten also schlechter als bei der binären Suche auf Feldern. Im Mittel verhalten sich Suchbäume aber wesentlich besser (O(log N)). Zusätzlich versucht man durch gezielte Reorganisation eine gute Balancierung zu erreichen (siehe Kapitel 5). Mit modifizieren Operationen kann man das Auf- und Abbauen der Suchbäume vermeiden und damit die Effizienz steigern Abstraktion mittels Polymorphie und Funktionen höherer Ordnung Überblick: Grundbegriffe der Typisierung Polymorphie als Abstraktionsmittel Typsysteme und Typinferenz Einführung in Funktionen höherer Ordnung Wichtige Funktionen höherer Ordnung Abstraktionen über Datenstrukturen Typisierung Inhalte: Was ist ein Typ? Ziele der Typisierung Polymorphie und parametrische Typen Typsystem von ML und Typinferenz Fast alle modernen Spezifikations- und Programmiersprachen besitzen ein Typsystem. Was ist ein Typ? Ein Typ beschreibt Eigenschaften von Elementen der Modellierung oder Programmierung: Elementare Typen stehen häufig für die Eigenschaft, zu einer bestimmten Wertemenge zu gehören ( bool, int, char, string,... ). Zusammengesetzte Typen beschreiben die genaue Struktur ihrer Elemente ( Tupel-, Listenund Funktionstypen). Parametrische Typen beschreiben bestimmte Eigenschaften und lassen andere offen; z.b.: - Elemente vom Typ a list sind homogene Listen; man kann also null, hd, tl anwen. Offen bleibt z.b. der Ergebnistyp von hd. - Elemente vom Typ a * a list sind Paare, so dass die Funktionen für Paare angewet werden können. Außerdem besitzen sie die Eigenschaft, dass die zweite Komponente immer eine Liste ist, deren Elemente vom selben Typ sind wie die erste Komponente: fun f ( p:('a * 'a list ) ): 'a list = let val (fst,scd) = p in fst::scd

11 Ziele der Typisierung Die Typisierung verfolgt drei Ziele: Automatische Erkennung von Programmierfehlern (durch Übersetzer, Interpreter); Verbessern der Lesbarkeit von Programmen; Ermöglichen effizienterer Implementierungen. Typisierung war lange Zeit nicht unumstritten. Hauptgegenargumente sind: zusätzlicher Schreibaufwand Einschränkung der Freiheit: - inhomogene Listen - Nutzen der Repräsentation von Daten im Rechner Wir konzentrieren uns hier auf das erste Ziel. Zentrale Idee: - Für jeden Ausdruck und jede Funktion wird ein Typ festgelegt. - Prüfe, ob die Typen der aktuellen Parameterausdrücke mit der Signatur der angeweten Funktion oder Operation übereinstimmen. Beispiele: f: int int, dann sind: (Typprüfung von Ausdrücken) f 7, f (hd [ 1,2,3 ]), f ( f 78 ) + 9 f true, [ f, 5.6 ], f hd nicht typkorrekt. typkorrekt; Beispiel: Es gibt viele Programme, die nicht typkorrekt sind, sich aber trotzdem zur Laufzeit gutartig verhalten; z.b: Aufgabe 1: Schreibe eine Funktion mp: - Eingabe: Liste von Paaren entweder vom Typ bool * int oder bool * real - Zulässige Listen: Wenn 1. Komponente true, dann 2. Komponente vom Typ int, sonst vom Typ real - Summiere die Listenelemente und liefere ein Paar mit beschriebener Eigenschaft Realisierung in ML-Notation (kein ML-Programm, da nicht typkorrekt!): fun mp [ ] = (true, 0) mp ((true,n)::xs ) = case mp xs of (true,k) => (true, k+n ) (false,q) => (false, q + (real n)) mp ((false,r)::xs ) = case mp xs of (true,k) => (false, (real k) + r) (false,q) => (false, q + r) Wegen fehler Typisierung ist es schwierig, die Überladung des Pluszeichens aufzulösen. Aufgabe 2: Schreibe eine Funktion, - die ein n-tupel (n>0) nimmt und - die erste Komponente des Tupels liefert. Realisierung in ML-Notation (kein ML-Programm, da nicht typkorrekt!) : - fun f n = #1 n; stdin: Error: unresolved flex record (can't tell what fields there are besides #1) Polymorphie und parametrische Typen Im Allg. bedeutet Polymorphie Vielgestaltigkeit. In der Programmierung bezieht sich Polymorphie auf die Typisierung bzw. das Typsystem. Begriffsklärung: (polymorphes Typsystem) Das Typsystem einer Sprache S beschreibt, - welche Typen es in S gibt bzw. wie neue Typen deklariert werden; - wie den Ausdrücken von S ein Typ zugeordnet wird; - welche Regeln typisierte Ausdrücke erfüllen müssen. Ein Typsystem heißt polymorph, wenn es Werte bzw. Objekte gibt, die zu mehreren Typen gehören

12 Man unterscheidet: - Parametrische Polymorphie - Subtyp-Polymorphie (vgl. Typisierung in Java) Oft spricht man im Zusammenhang mit der Überladung von Funktions- oder Operatorsymbolen von Ad-hoc-Polymorphie. Beispiel: Dem +-Operator könnte man in ML den Typ int * int int oder real * real real geben. In polymorphen Typsystemen gibt es meist eine Relation ist_spezieller_als zwischen Typen T1, T2 : T1 heißt spezieller als T2, wenn die Eigenschaften, die T1 garantiert, die Eigenschaften von T2 implizieren (umgekehrt sagt man: T2 ist allgemeiner als T1). Beispiel: Der Typ int list ist spezieller als der parametrische Typ a list. Insbesondere gilt: Jeder Wert vom Typ int list kann überall dort benutzt werden, wo ein Wert vom Typ a list erwartet wird. Typsystem von ML und Typinferenz Typen werden in ML durch Typausdrücke beschrieben: - Typkonstanten sind die elementaren Datentypen: bool, int, char, string, real,... - Typvariablen: a, meinetypvar, a, gtyp - Ausdrücke gebildet mit Typkonstruktoren: Sind TA, TA1, TA2, TA3,... Typausdrücke, dann sind die folgen Ausdrücke auch Typausdrücke: TA1 * TA2 TA1 * TA2 * TA3... TA list TA1 -> TA2... Typ der Paare Typ der Triple Listentyp Funktionstyp Beispiele: (Typausdrücke) - int, bool - a, b - int * bool, int * a, int * b * a - int list, a list, (int * b * a ) list - int -> int, a list -> (int * b * a ) list - (int -> int) -> (real -> real) Präzedenzregeln für Typkonstruktoren: list bindet am stärksten * bindet am zweitstärksten -> bindet am schwächsten und ist rechtsassoziativ Begriffserklärung: (Vergleich von Typen) Seien TA und TB Typausdrücke und var(ta) die Menge der Typvariablen, die in TA vorkommen. Eine Variablensubstitution ist eine Abbildung β von var(ta) auf die Menge der Typausdrücke. Bezeichne TA β den Typausdruck, den man aus TA erhält, wenn man alle Variablen v in TA konsistent durch β (v) ersetzt. TB ist spezieller als TA, wenn es eine Variablensubstitution β gibt, so dass TA β = TB. TA und TB bezeichnen den gleichen Typ, wenn TA spezieller als TB ist und TB spezieller als TA. Beispiele: Beispiele: (Präzedenzen) int list ist spezieller als a list a list ist spezieller als b list und umgekehrt int * bool list steht für int * ( bool list ) int * real -> int list steht für (int * real) -> (int list ) a -> char -> bool steht für a -> ( char -> bool ) a -> a ist spezieller als a -> b int list * b und c list * bool sind nicht vergleichbar, d.h. der erste Ausdruck ist nicht spezieller als der zweite und der zweite nicht spezieller als der erste

13 Bezeichne TE die Menge der Typausdrücke in ML. - Die ist_spezieller_als Relation auf TE x TE ist reflexiv und transitiv, aber nicht antisymmetrisch. - Identifiziert man alle Typausdrücke, die den gleichen Typ bezeichnen, erhält man die Menge T der Typen. ( T, ist _spezieller_als ) ist eine partielle Ordnung. Das Typsystem von ML ist feiner als hier dargestellt. Insbesondere wird zwischen allen Typen und der Teilmenge von Typen unterschieden, auf denen die Gleichheit definiert ist, den sogenannten Gleichheitstypen. Beispiel: - fun listcompare [] [] = true listcompare [] (x::xs) = false listcompare (x::xs) [] = false listcompare (x::xs) (y::ys) = if x=y then listcompare xs ys else false; val listcompare = fn : ''a list -> ''a list -> bool Typvariablen für Gleichheitstypen beginnen mit zwei Hochkommas. Damit verstehen wir nun auch den Typ der Gleichheitsfunktion in ML: - val eq = fn (x,y) => x = y ; val eq = fn : ''a * ''a -> bool Damit ist gesagt, was Typen in ML sind. Typregeln in ML: Wir nennen eine Ausdruck A typannotiert, wenn A und allen Teilausdrücken von A ein Typ zugeordnet ist. Beispiel: Die Typannotationen von abs ~2 ist ( (abs:int->int)(~2:int) ):int Die Typregeln legen fest, wann ein typannotierter Ausdruck typkorrekt ist. In ML muss gelten: - die Typen der formalen Parameter müssen gleich den Typen der aktuellen Parameter sein. - if-then-else, andalso, orelse müssen korrekt typisierte Parameter haben Typinferenz: Typinferenz bedeutet das Ableiten der Typannotation für Ausdrücke aus den gegebenen Deklarationsinformationen. Sie ist in gängigen Programmiersprachen oft recht einfach, in modernen Programmiersprachen teilweise recht komplex. Beispiele: 1. Leere Liste: - val a = [ ]; val a = [ ] : 'a list 3. Einsortieren in geordnete Liste mit Vergleichsfunktion: - fun einsortieren2 (v,p1,p2) = case p2 of x::xs => if v (p1,x) then p1::p2 [ ] => [ p1 ] ; else x::(einsortieren2 (v,p1,xs)) val einsortieren2 = fn: ('a * 'a-> bool) * a * 'a list -> 'a list Bei der Typinferenz versucht man immer den allgemeinsten Typ herauszufinden. 2. Einsortieren in geordnete Liste von Zahlen: - fun einsortieren (p1,p2) = case p2 of x::xs => if p1 <= x then p1::p2 else x::(einsortieren (p1,xs)) [ ] => [ p1 ] ; val einsortieren = fn : int * int list -> int list

14 3.3.2 Funktionen höherer Ordnung Überblick: Einführung in Funktionen höherer Ordnung Wichtige Funktionen höherer Ordnung Abstraktionen über Datenstrukturen Einführung Funktionen höherer Ordnung sind Funktionen, die Sprachliche Aspekte: Alle wesentlichen Sprachmittel zum Arbeiten mit Funktionen höherer Ordnung sind bereits bekannt: - Funktionsabstraktion - Funktionsdeklaration - Funktionsanwung - Funktionstypen - Funktionen als Argumente nehmen und/oder - Funktionen als Ergebnis haben. Selbstverständlich sind auch Listen oder Tupel von Funktionen als Argumente oder Ergebnisse möglich. Eine Funktion F, die Funktionen als Argumente nimmt und als Ergebnis liefert, nennt man häufig auch ein Funktional. Funktionale, die aus der Schule bekannt sind, sind - Differenzial - unbestimmtes Integral Konzeptionelle Aspekte: Zwei konzeptionelle Aspekte liegen der Anwung von Funktionen höherer Ordnung in der Software- Entwicklung zugrunde: 1. Abstraktion und Wiederverwung 2. Metaprogrammierung, d.h. das Entwickeln von Programmen, die Programme als Argumente und Ergebnisse haben. Wir betrachten im Folgen den ersten Aspekt Aufgabe: Sortiere eine Liste xl von Zahlen Rekursionsidee: - Sortiere zunächst den Rest der Liste. - Das ergibt eine sortierte Liste xs. - Sortiere das erste Element von xl in xs ein. Umsetzung in ML: - fun einsortieren e [ ] = [ e ] einsortieren e (x::xr) = if e <= x then e::x::xr else x::(einsortieren e xr) ; val einsortieren = fn : int -> int list -> int list - fun sort [] = [] sort (x::xr) = einsortieren x (sort xr); val it = fn : int list -> int list Frage: - Warum kann man mit sort nicht auch Werte der Typen char, string, real, etc. sortieren? Antwort: Auflösung der Überladung von <= Wiederverwung zur Sortierung von real-listen: - fun einsortieren (e:real) [] = [e] einsortieren e (x::xr) = if e <= x then e::x::xr else x::(einsortieren e xr) ; val einsortieren = fn : real -> real list -> real list Unbefriedig: Verändern einer Funktion, die für den Anwer von sort ggf. nicht bekannt. Abstraktion durch Parametrisierung: Wiederverwung von sort wird möglich, wenn wir die Vergleichsoperation als zusätzlichen Parameter einführen: - fun einsortieren vop e [ ] = [ e ] einsortieren vop e (x::xr) = if vop (e,x) then e::x::xr else x::(einsortieren vop e xr) ; - fun sort vop [ ] = [ ] sort vop (x::xr) = einsortieren vop x (sort vop xr) ;

15 Anwung: - sort (op <=) [ 2,3, 968,~98,34,0 ] ; val it = [~98,0,2,3,34,968] : int list - sort (op >=) [ 2,3, 968,~98,34,0 ] ; val it = [968,34,3,2,0,~98] : int list - sort ((op >=):real*real->bool) [1.0, 1e~4 ]; val it = [1.0,0.0001] : real list - val strcmp = ((op <=):string*string->bool); - sort strcmp ["Abbay", "Abba", "Ara", "ab"]; val it = ["Abba","Abbay","Ara","ab"] : string list Polymorphe Funktionen können häufig auch Funktionen als Parameter nehmen. Beispiel: 1. Funktion cons: abs::fac::nil 2. Identitätsfunktion: (fn x => x) (fn x => x) (Ausdruck ist von der Typisierung her problematisch) Wichtige Funktionen höherer Ordnung Dieser Abschnitt betrachtet einige Beispiele für Funktionen höherer Ordnung und diskutiert das Arbeiten mit solchen Funktionen. Funktionskomposition: - fun fcomp f g = (fn x => f(g x)); val fcomp = fn : ('a->'b)->('c->'a)->'c->'b In ML gibt es die vordefinierte Infix-Operation o für die Funktionskomposition. Map: Anwung einer Funktion auf die Elemente einer Liste map f [ x1,..., xn ] = [ (f x1),..., (f xn) ] - fun map f [] = [] map f (x::xs) = (f x):: map f xs; Anwungsbeispiel 1: - map size [ Schwerter, zu, Pflugscharen ]; val it = [9,2,12] : int list Anwungsbeispiel 2: Aufgabe: - Eingabe: Liste von Listen von ganzen Zahlen - Ausgabe: gleiche Listenstruktur, Zahlen verdoppelt - fun double n = 2*n; - map (map double) [ [1,2], [34829] ]; val it = [ [2,4], [69658] ] : int list list Currying und Schönfinkeln: Funktionen mit einem Argumenttupel kann man die Argumente auch sukzessive geben. Dabei entstehen Funktionen höherer Ordnung. Beispiele: - fun times m n = m * n; val times = fn : int -> int -> int - val double = times 2; val double = fn : int -> int - double 5; val it = 10 : int Zwei Varianten von map im Vergleich: 1. Die beiden Argumente als Paar: - fun map (f, [ ]) = [ ] map (f,(x::xs)) = (f x) :: map (f,xs); val map = fn: ('a->'b) * 'a list -> 'b list 2. Die Argumente nacheinander ( gecurryt ): - fun map f [] = [] map f (x::xs) = (f x) :: map f xs; val map = fn: ('a->'b) -> 'a list -> 'b list Die gecurryte Fassung ist flexibler: Sie kann nicht nur auf ein vollständiges Argumententupel angewet werden, sondern auch zur Definition neuer Funktionen mittels partieller Anwung benutzt werden. Beispiele: val double = times 2 ; val ilsort = sort (op <=) ; val doublelist = map double ;

16 Curryen von Funktionen: Die Funktion curry liefert zu einer Funktion auf Paaren die zugehörige gecurryte Funktion: - fun curry f x y = f (x,y); val curry = fn: ('a*'b->'c) -> 'a -> 'b -> 'c Prüfen von Prädikaten für Listenelemente: Die folgen Funktionen exists und all prüfen, ob - es Elemente in einer Liste gibt, die ein gegebenes Prädikat erfüllen bzw. - alle Elemente einer Liste ein gegebenes Prädikat erfüllen. - fun exists pred [ ] = false exists pred (x::xs) = pred x orelse exists pred xs; val exists = fn: ('a->bool) -> 'a list -> bool - fun all pred [ ] = true all pred (x::xs) = pred x andalso all pred xs; val all = fn : ('a -> bool) -> 'a list -> bool Anwungsbeispiel: Prüfen, ob ein Element in einer Liste enthalten ist: - fun ismember x xs = exists (fn y=> x=y) xs; val ismember = fn : ''a -> ''a list -> bool Punktweise Veränderung von Funktionen: Die Veränderung einer Funktion an einem Punkt des Argumentbereichs: - fun update f x v y = if x = y then v else f y ; val update = fn:(''a->'b)->''a->'b-> ''a -> 'b Falten von Listen: Eine sehr verbreitete Funktion ist das Falten einer Liste mittels einer binären Funktion und einem neutralen Element: foldr n [e1, e2,..., en ] = e1 (e2 (...(en n)...)) Deklaration von foldr: - fun foldr f n [ ] = n foldr f n (x::xs) = f (x,foldr f n xs); val foldr = fn: ('a*'b->'b)->'b->'a list->'b Auf Basis von foldr lassen sich viele Listenfunktionen direkt, d.h. ohne Rekursion definieren: - val sum = foldr op+ 0 ; val sum = fn : int list -> int - fun l2 = foldr op:: l2 l1; = fn : 'a list * 'a list -> 'a list - fun implode1 cl = foldr op^ "" (map str cl); val implode = fn : char list -> string - val implode2 = foldr (fn(x,y)=>(str x)^y) ; val implode2 = fn : char list -> string Die Programmentwicklung mittels Funktionen höherer Ordnung (funktionale Programmierung) ist ein erstes Beispiel für: das Zusammensetzen komplexerer Bausteine, programmiertechnische Variationsmöglichkeiten, die Problematik der Wiederverwung: - die Bausteine müssen bekannt sein, - die Bausteine müssen ausreich generisch sein. Abstraktion über Datenstrukturen Datenstrukturen lassen sich bzgl. einiger in ihnen verweten Typen und Funktionen parametrisieren. Der Parameter ist dann kein Wert sondern eine Struktur. Der Typ des Parameters, d.h. dessen Eigenschaften, werden durch eine Signatur angegeben. Eine derart abstrahierte/parametrisierte Datenstruktur nennt man in ML einen Funktor. Ein Funktor nimmt eine Datenstruktur als Parameter und liefert eine Datenstruktur als Ergebnis. Exemplarisch betrachten wir hier Dictionaries, die bzgl. - des Schlüsseltyps key - des Typs der Daten data - eines Dummy-Elements dummydata und - der Vergleichsoperation auf Schlüsseln parametrisiert sind. signature ENTRY = sig eqtype key; type data; val dummydata : data; val leq: key * key -> bool

17 Der Funktor nimmt also eine Datenstruktur mit Signatur ENTRY als Parameter und liefert eine Datenstruktur für Dictionaries: functor MakeBST ( Et: ENTRY ): sig type dict; val Empty: dict; val get: dict * Et.key -> bool * Et.data ; val put: dict * Et.key * Et.data -> dict ; val remove: dict * Et.key -> dict = struct open Et; type dataset = key * data ; datatype btree = Node of (dataset*btree*btree) Empty ; type dict = btree ; fun get (Empty, k) = (false,dummydata) get (Node ((km,s),l,r),k) = if k = km then (true,s) else if leq(k,km) then get (l,k) else get (r,k)... (* Fortsetzung auf kommer Folie *) 222 (* vgl. Folie 188, 190 und 194 *) fun put (Empty,k,s) = Node((k,s),Empty,Empty) put (Node ((km,sm),l,r),k,s) = if k = km then Node ((k,s),l,r) else if leq(k,km) then Node ((km,sm),put(l,k,s),r) else (* leq(km,k) *) Node ((km,sm),l,put(r,k,s)) fun removemin (Node(d,Empty,r)) = (d,r) removemin (Node(d,l,r)) = let val (min,ll) = removemin l; in (min, Node(d,ll,r)) fun remove (Empty,k) = Empty remove (Node((km,s),l,r),k) = if leq(k,km) then Node ((km,s), remove(l,k), r) else if leq(km,k) then Node ((km,s), l, remove(r,k)) else (* k = km *) case (l,r) of (Empty,rt) => r (lt,empty) => l (lt,rt) => let val (min,rr) = removemin r in Node (min,l,rr) 223 Zur Anwung übergeben wir dem Funktor eine Datenstruktur mit Signatur ENTRY: structure IntStringDataset = struct type key = int; type data = string; val dummydata = ""; val leq = op < structure Dictionary = MakeBST(IntStringDataset); Bei der Abstraktion über Datenstrukturen übernimmt die Signatur die Rolle des Parameter- und Ergebnistyps. Wie bei der Funktionsabstraktion geht es auch bei der Abstraktion über Datenstrukturen darum, den einmal geschriebenen Rumpf für mehrere unterschiedliche Eingaben wiederzuverwen. Bzgl. der präzisen Abstraktion von Programmen hinsichtlich unterschiedlicher Aspekte sind funktionale Programmiersprachen am weitesten. Bemerkungen: (zur ML-Einführung) Ziel des Kapitels war es nicht, eine umfasse ML-Einführung zu geben. ML dient hier vor allem als Hilfsmittel, wichtige Konzepte zu erläutern. Die meisten zentralen Konstrukte wurden behandelt. Es fehlt Genaueres zu: - Fehlerbehandlung - Modularisierungskonstrukte (Signaturen, Strukturen, abstrakte Typen, Funktoren) - Konstrukte zur imperativen Programmierung - Ein-/Ausgabe-Operationen; z.b. print : string -> unit Viele Aspekte der Programmierumgebung wurden vernachlässigt

Bemerkung: Heapsort. Begriffsklärung: (zu Bäumen) Begriffsklärung: (zu Bäumen) (2) Heapsort verfeinert die Idee des Sortierens durch Auswahl:

Bemerkung: Heapsort. Begriffsklärung: (zu Bäumen) Begriffsklärung: (zu Bäumen) (2) Heapsort verfeinert die Idee des Sortierens durch Auswahl: Heapsort Bemerkung: Heapsort verfeinert die Idee des Sortierens durch Auswahl: Minimum bzw. Maximum wird nicht durch lineare Suche gefunden, sondern mit logarithmischem Aufwand durch Verwendung einer besonderen

Mehr

Abstraktion mittels Polymorphie und Funktionen höherer Ordnung. Abschnitt 3.3. Polymorphie und Funktionen höherer Ordnung. Unterabschnitt 3.3.

Abstraktion mittels Polymorphie und Funktionen höherer Ordnung. Abschnitt 3.3. Polymorphie und Funktionen höherer Ordnung. Unterabschnitt 3.3. Abschnitt 3.3 Abstraktion mittels Polymorphie und Funktionen höherer Ordnung Überblick: Polymorphie und Funktionen höherer Ordnung Grundbegriffe der Typisierung Polymorphie als Abstraktionsmittel Typsysteme

Mehr

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume)

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen, Bäume) Fachrichtung 6.2 Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 15 (Linearer Speicher, Listen,

Mehr

Programmierung und Modellierung

Programmierung und Modellierung Programmierung und Modellierung Terme, Suchbäume und Pattern Matching Martin Wirsing in Zusammenarbeit mit Moritz Hammer SS 2009 2 Inhalt Kap. 7 Benutzerdefinierte Datentypen 7. Binärer Suchbaum 8. Anwendung:

Mehr

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny

Grundlagen der Informatik. Prof. Dr. Stefan Enderle NTA Isny Grundlagen der Informatik Prof. Dr. Stefan Enderle NTA Isny 2 Datenstrukturen 2.1 Einführung Syntax: Definition einer formalen Grammatik, um Regeln einer formalen Sprache (Programmiersprache) festzulegen.

Mehr

Programmierung und Modellierung

Programmierung und Modellierung Programmierung und Modellierung Benutzerdefinierte Datentypen Martin Wirsing in Zusammenarbeit mit Moritz Hammer SS 2009 2 Inhalt Kap. 7 Benutzerdefinierte Datentypen 1. Aufzählungstypen 2. Typen mit zusammengesetzten

Mehr

Kapitel 6: Typprüfung

Kapitel 6: Typprüfung Ludwig Maximilians Universität München Institut für Informatik Lehr- und Forschungseinheit für Datenbanksysteme Skript zur Vorlesung Informatik I Wintersemester 2006 Vorlesung: Prof. Dr. Christian Böhm

Mehr

7. Sortieren Lernziele. 7. Sortieren

7. Sortieren Lernziele. 7. Sortieren 7. Sortieren Lernziele 7. Sortieren Lernziele: Die wichtigsten Sortierverfahren kennen und einsetzen können, Aufwand und weitere Eigenschaften der Sortierverfahren kennen, das Problemlösungsparadigma Teile-und-herrsche

Mehr

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Einige andere Programmiersprachen. Typisierung in Haskell Haskell, Typen, und Typberechnung Grundlagen der Programmierung 3 A Typen, Typberechnung und Typcheck Prof. Dr. Manfred Schmidt-Schauß Ziele: Haskells Typisierung Typisierungs-Regeln Typ-Berechnung Milners

Mehr

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 13 (Queues, Binary Search)

Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 13 (Queues, Binary Search) Fachrichtung 6.2 Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2015/16) Wiederholungstutorium Lösungsblatt 13 (Queues, Binary Search)

Mehr

Grundlagen der Programmierung 3 A

Grundlagen der Programmierung 3 A Grundlagen der Programmierung 3 A Typen, Typberechnung und Typcheck Prof. Dr. Manfred Schmidt-Schauß Sommersemester 2017 Haskell, Typen, und Typberechnung Ziele: Haskells Typisierung Typisierungs-Regeln

Mehr

Grundlagen der Programmierung 2. Sortierverfahren

Grundlagen der Programmierung 2. Sortierverfahren Grundlagen der Programmierung 2 Sortierverfahren Prof. Dr. Manfred Schmidt-Schauÿ Künstliche Intelligenz und Softwaretechnologie 30. Mai 2006 Sortieren Ziel: Bringe Folge von Objekten in eine Reihenfolge

Mehr

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

Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken. Abstrakte Datentypen und Datenstrukturen/ Einfache Beispiele Abstrakter Datentyp (ADT): Besteht aus einer Menge von Objekten, sowie Operationen, die auf diesen Objekten wirken. Datenstruktur (DS): Realisierung

Mehr

Wiederholung ADT Menge Ziel: Verwaltung (Finden, Einfügen, Entfernen) einer Menge von Elementen

Wiederholung ADT Menge Ziel: Verwaltung (Finden, Einfügen, Entfernen) einer Menge von Elementen Was bisher geschah abstrakter Datentyp : Signatur Σ und Axiome Φ z.b. ADT Menge zur Verwaltung (Finden, Einfügen, Entfernen) mehrerer Elemente desselben Typs Spezifikation einer Schnittstelle Konkreter

Mehr

11. Elementare Datenstrukturen

11. Elementare Datenstrukturen 11. Elementare Datenstrukturen Definition 11.1: Eine dynamische Menge ist gegeben durch eine oder mehrer Mengen von Objekten sowie Operationen auf diesen Mengen und den Objekten der Mengen. Dynamische

Mehr

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen Vorlesung Datenstrukturen Binärbaum Suchbaum Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 356 Datenstruktur Binärbaum Strukturrepräsentation des mathematischen Konzepts Binärbaum

Mehr

Agenda. 1 Einleitung. 2 Binäre Bäume. 3 Binäre Suchbäume. 4 Rose Trees. 5 Zusammenfassung & Ausblick. Haskell Bäume. Einleitung.

Agenda. 1 Einleitung. 2 Binäre Bäume. 3 Binäre Suchbäume. 4 Rose Trees. 5 Zusammenfassung & Ausblick. Haskell Bäume. Einleitung. Vortrag: Bäume in Haskell Bäume in Haskell Vortrag Christoph Forster Thomas Kresalek Fachhochschule Wedel University of Applied Sciences 27. November 2009 Christoph Forster, Thomas Kresalek 1/53 Vortrag

Mehr

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie

Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom : Typvariablen und Polymorphie Rev. 2749 1 [28] Praktische Informatik 3: Funktionale Programmierung Vorlesung 4 vom 04.11.2014: Typvariablen und Polymorphie Christoph Lüth Universität Bremen Wintersemester 2014/15 2 [28] Fahrplan Teil

Mehr

Vorlesung Informatik 2 Algorithmen und Datenstrukturen

Vorlesung Informatik 2 Algorithmen und Datenstrukturen Vorlesung Informatik 2 Algorithmen und Datenstrukturen (18 Bäume: Grundlagen und natürliche Suchbäume) Prof. Dr. Susanne Albers Bäume (1) Bäume sind verallgemeinerte Listen (jedes Knoten-Element kann mehr

Mehr

8. A & D - Heapsort. Werden sehen, wie wir durch geschicktes Organsieren von Daten effiziente Algorithmen entwerfen können.

8. A & D - Heapsort. Werden sehen, wie wir durch geschicktes Organsieren von Daten effiziente Algorithmen entwerfen können. 8. A & D - Heapsort Werden sehen, wie wir durch geschicktes Organsieren von Daten effiziente Algorithmen entwerfen können. Genauer werden wir immer wieder benötigte Operationen durch Datenstrukturen unterstützen.

Mehr

Datenstrukturen & Algorithmen

Datenstrukturen & Algorithmen Datenstrukturen & Algorithmen Matthias Zwicker Universität Bern Frühling 2010 Übersicht Binäre Suchbäume Einführung und Begriffe Binäre Suchbäume 2 Binäre Suchbäume Datenstruktur für dynamische Mengen

Mehr

Informatik II, SS 2014

Informatik II, SS 2014 Informatik II SS 2014 (Algorithmen & Datenstrukturen) Vorlesung 7 (21.5.2014) Binäre Suche, Hashtabellen I Algorithmen und Komplexität Abstrakte Datentypen : Dictionary Dictionary: (auch: Maps, assoziative

Mehr

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

Informatik II Vorlesung am D-BAUG der ETH Zürich Informatik II Vorlesung am D-BAUG der ETH Zürich Vorlesung 9, 2.5.2016 [Nachtrag zu Vorlesung : Numerische Integration, Zusammenfassung Objektorientierte Programmierung] Dynamische Datenstrukturen II:

Mehr

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen Vorlesung Datenstrukturen Prioritätswarteschlangen Maike Buchin 18. und 23.5.2017 Prioritätswarteschlange Häufiges Szenario: dynamische Menge von Objekten mit Prioritäten, z.b. Aufgaben, Prozesse, in der

Mehr

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

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 Teil : Suchen Problemstellung Elementare Suchverfahren Hashverfahren Binäre Suchbäume (Wiederholung aus Prog 2) Bäume: Begriffe, Eigenschaften und Traversierung Binäre Suchbäume Gefädelte Suchbäume Ausgeglichene

Mehr

Algorithmen und Datenstrukturen 1

Algorithmen und Datenstrukturen 1 Algorithmen und Datenstrukturen 1 6. Vorlesung Martin Middendorf / Universität Leipzig Institut für Informatik middendorf@informatik.uni-leipzig.de studla@bioinf.uni-leipzig.de Merge-Sort Anwendbar für

Mehr

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell):

Was bisher geschah. deklarative Programmierung. funktionale Programmierung (Haskell): Was bisher geschah deklarative Programmierung funktional: Programm: Menge von Termgleichungen, Term Auswertung: Pattern matsching, Termumformungen logisch: Programm: Menge von Regeln (Horn-Formeln), Formel

Mehr

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

Binäre Suchbäume. Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps Binäre Suchbäume Mengen, Funktionalität, Binäre Suchbäume, Heaps, Treaps Mengen n Ziel: Aufrechterhalten einer Menge (hier: ganzer Zahlen) unter folgenden Operationen: Mengen n Ziel: Aufrechterhalten einer

Mehr

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen:

Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen: Verarbeitung unendlicher Datenstrukturen Jetzt können wir z.b. die unendliche Liste aller geraden Zahlen oder aller Quadratzahlen berechnen: take 1 0 ( f i l t e r ( fn x => x mod 2=0) nat ) ; val it =

Mehr

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

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 Prof. aa Dr. E. Ábrahám Datenstrukturen und Algorithmen SS Lösung - Präsenzübung.05.0 F. Corzilius, S. Schupp, T. Ströder Aufgabe (Asymptotische Komplexität): (6 + 0 + 6 = Punkte) a) Geben Sie eine formale

Mehr

Informatik II, SS 2014

Informatik II, SS 2014 Informatik II SS 2014 (Algorithmen & Datenstrukturen) Vorlesung 11 (4.6.2014) Binäre Suchbäume II Algorithmen und Komplexität Binäre Suchbäume Binäre Suchbäume müssen nicht immer so schön symmetrisch sein

Mehr

Programmieren in Haskell Programmiermethodik

Programmieren in Haskell Programmiermethodik Programmieren in Haskell Programmiermethodik Peter Steffen Universität Bielefeld Technische Fakultät 12.01.2011 1 Programmieren in Haskell Bisherige Themen Was soll wiederholt werden? Bedienung von hugs

Mehr

Was bisher geschah ADT Menge mit Operationen: Suche nach einem Element Einfügen eines Elementes Löschen eines Elementes Realisierung durch

Was bisher geschah ADT Menge mit Operationen: Suche nach einem Element Einfügen eines Elementes Löschen eines Elementes Realisierung durch Was bisher geschah ADT Menge mit Operationen: Suche nach einem Element Einfügen eines Elementes Löschen eines Elementes Realisierung durch verschiedene Datenstrukturen: lineare Datenstrukturen: Array,

Mehr

Programmieren I. Kapitel 7. Sortieren und Suchen

Programmieren I. Kapitel 7. Sortieren und Suchen Programmieren I Kapitel 7. Sortieren und Suchen Kapitel 7: Sortieren und Suchen Ziel: Varianten der häufigsten Anwendung kennenlernen Ordnung Suchen lineares Suchen Binärsuche oder Bisektionssuche Sortieren

Mehr

Mehrwegbäume Motivation

Mehrwegbäume Motivation Mehrwegbäume Motivation Wir haben gute Strukturen (AVL-Bäume) kennen gelernt, die die Anzahl der Operationen begrenzen Was ist, wenn der Baum zu groß für den Hauptspeicher ist? Externe Datenspeicherung

Mehr

Algorithmen und Datenstrukturen Heapsort

Algorithmen und Datenstrukturen Heapsort Algorithmen und Datenstrukturen 2 5 Heapsort In diesem Kapitel wird Heapsort, ein weiterer Sortieralgorithmus, vorgestellt. Dieser besitzt wie MERGE-SORT eine Laufzeit von O(n log n), sortiert jedoch das

Mehr

Definition Ein Heap (priority queue) ist eine abstrakte Datenstruktur mit folgenden Kennzeichen:

Definition Ein Heap (priority queue) ist eine abstrakte Datenstruktur mit folgenden Kennzeichen: HeapSort Allgemeines Sortieralgorithmen gehören zu den am häufigsten angewendeten Algorithmen in der Datenverarbeitung. Man hatte daher bereits früh ein großes Interesse an der Entwicklung möglichst effizienter

Mehr

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

Datenstrukturen Teil 2. Bäume. Definition. Definition. Definition. Bäume sind verallgemeinerte Listen. Sie sind weiter spezielle Graphen Bäume sind verallgemeinerte Listen Datenstrukturen Teil 2 Bäume Jeder Knoten kann mehrere Nachfolger haben Sie sind weiter spezielle Graphen Graphen bestehen aus Knoten und Kanten Kanten können gerichtet

Mehr

Kurs 1663 Datenstrukturen" Musterlösungen zur Klausur vom Seite 1. Musterlösungen zur Hauptklausur Kurs 1663 Datenstrukturen 15.

Kurs 1663 Datenstrukturen Musterlösungen zur Klausur vom Seite 1. Musterlösungen zur Hauptklausur Kurs 1663 Datenstrukturen 15. Kurs 1663 Datenstrukturen" Musterlösungen zur Klausur vom 15.08.98 Seite 1 Musterlösungen zur Hauptklausur Kurs 1663 Datenstrukturen 15. August 1998 Kurs 1663 Datenstrukturen" Musterlösungen zur Klausur

Mehr

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Überladung und Konversion in Haskell. Typisierung in Haskell

Haskell, Typen, und Typberechnung. Grundlagen der Programmierung 3 A. Überladung und Konversion in Haskell. Typisierung in Haskell Haskell, Typen, und Typberechnung Grundlagen der Programmierung 3 A Typen, Typberechnung und Typcheck Prof. Dr Manfred Schmidt-Schauß Ziele: Haskells Typisierung Typisierungs-Regeln Typ-Berechnung Sommersemester

Mehr

8. Sortieren II. 8.1 Heapsort. Heapsort. [Max-]Heap 6. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften

8. Sortieren II. 8.1 Heapsort. Heapsort. [Max-]Heap 6. Heapsort, Quicksort, Mergesort. Binärer Baum mit folgenden Eigenschaften Heapsort, Quicksort, Mergesort 8. Sortieren II 8.1 Heapsort [Ottman/Widmayer, Kap. 2.3, Cormen et al, Kap. 6] 9 210 Heapsort [Max-]Heap 6 Inspiration von Selectsort: Schnelles Einfügen Binärer Baum mit

Mehr

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit

Counting - Sort [ [ ] [ [ ] 1. SS 2008 Datenstrukturen und Algorithmen Sortieren in linearer Zeit Counting-Sort Counting - Sort ( A,B,k ). for i to k. do C[ i]. for j to length[ A]. do C[ A[ j ] C[ A[ j ] +. > C[ i] enthält Anzahl der Elemente in 6. for i to k. do C[ i] C[ i] + C[ i ]. > C[ i] enthält

Mehr

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen Vorlesung Datenstrukturen Heaps Dr. Frank Seifert Vorlesung Datenstrukturen - Sommersemester 2016 Folie 469 Prioritätswarteschlange Problem Häufig ist das Prinzip einer einfachen Warteschlangen-Datenstruktur

Mehr

Kapitel 12: Induktive

Kapitel 12: Induktive Kapitel 12: Induktive Datenstrukturen Felix Freiling Lehrstuhl für Praktische Informatik 1 Universität Mannheim Vorlesung Praktische Informatik I im Herbstsemester 2009 Folien nach einer Vorlage von H.-Peter

Mehr

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

(a, b)-bäume / 1. Datenmenge ist so groß, dass sie auf der Festplatte abgespeichert werden muss. (a, b)-bäume / 1. Szenario: Datenmenge ist so groß, dass sie auf der Festplatte abgespeichert werden muss. Konsequenz: Kommunikation zwischen Hauptspeicher und Festplatte - geschieht nicht Byte für Byte,

Mehr

Beispiele: (Funktionen auf Listen) (3) Bemerkungen: Die Datenstrukturen der Paare (2) Die Datenstrukturen der Paare

Beispiele: (Funktionen auf Listen) (3) Bemerkungen: Die Datenstrukturen der Paare (2) Die Datenstrukturen der Paare Beispiele: (Funktionen auf Listen) (3) Bemerkungen: 5. Zusammenhängen der Elemente einer Liste von Listen: concat :: [[a]] -> [a] concat xl = if null xl then [] else append (head xl) ( concat (tail xl))

Mehr

Informatik II, SS 2014

Informatik II, SS 2014 Informatik II SS 2014 (Algorithmen & Datenstrukturen) Vorlesung 10 (3.6.2014) Binäre Suchbäume I Algorithmen und Komplexität Zusätzliche Dictionary Operationen Dictionary: Zusätzliche mögliche Operationen:

Mehr

Strukturelle Rekursion und Induktion

Strukturelle Rekursion und Induktion Kapitel 2 Strukturelle Rekursion und Induktion Rekursion ist eine konstruktive Technik für die Beschreibung unendlicher Mengen (und damit insbesondere für die Beschreibung unendliche Funktionen). Induktion

Mehr

Dies ist gerade der konstruktive Schritt beim Aufbau von Binomialbäumen.

Dies ist gerade der konstruktive Schritt beim Aufbau von Binomialbäumen. Linken von Bäumen: Zwei Bäume desselben Wurzel-Rangs werden unter Einhaltung der Heap-Bedingung verbunden. Sind k 1 und k 2 die Wurzeln der zwei zu linkenden Bäume, so wird ein neuer Baum aufgebaut, dessen

Mehr

Vorlesung Datenstrukturen

Vorlesung Datenstrukturen Vorlesung Datenstrukturen Sortierte Folgen Maike Buchin 30.5., 1.6., 13.6.2017 Sortierte Folgen Häufiges Szenario: in einer Menge von Objekten mit Schlüsseln (aus geordnetem Universum) sollen Elemente

Mehr

1. Einfach verkettete Liste unsortiert 2. Einfach verkettete Liste sortiert 3. Doppelt verkettete Liste sortiert

1. Einfach verkettete Liste unsortiert 2. Einfach verkettete Liste sortiert 3. Doppelt verkettete Liste sortiert Inhalt Einführung 1. Arrays 1. Array unsortiert 2. Array sortiert 3. Heap 2. Listen 1. Einfach verkettete Liste unsortiert 2. Einfach verkettete Liste sortiert 3. Doppelt verkettete Liste sortiert 3. Bäume

Mehr

4.1 Bäume, Datenstrukturen und Algorithmen. Zunächst führen wir Graphen ein. Die einfachste Vorstellung ist, dass ein Graph gegeben ist als

4.1 Bäume, Datenstrukturen und Algorithmen. Zunächst führen wir Graphen ein. Die einfachste Vorstellung ist, dass ein Graph gegeben ist als Kapitel 4 Bäume 4.1 Bäume, Datenstrukturen und Algorithmen Zunächst führen wir Graphen ein. Die einfachste Vorstellung ist, dass ein Graph gegeben ist als eine Menge von Knoten und eine Menge von zugehörigen

Mehr

Die Schnittstelle Comparable

Die Schnittstelle Comparable Die Schnittstelle Comparable Wir wollen Such- und Sortieroperationen für beliebige Objekte definieren. Dazu verwenden wir die vordefinierte Schnittstelle Comparable: public interface Comparable { int compareto(object

Mehr

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6

Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6 Robert Elsässer u.v.a. Paderborn, 29. Mai 2008 Beispiellösungen zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 6 Aufgabe 1 (6 Punkte): Zunächst sollte klar sein, daß ein vollständiger Binärer

Mehr

Datenstrukturen und Algorithmen

Datenstrukturen und Algorithmen Joost-Pieter Katoen Datenstrukturen und Algorithmen 1/32 Datenstrukturen und Algorithmen Vorlesung 7: Sortieren (K2) Joost-Pieter Katoen Lehrstuhl für Informatik 2 Software Modeling and Verification Group

Mehr

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5

Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5 Robert Elsässer Paderborn, den 15. Mai 2008 u.v.a. Beispiellösung zu den Übungen Datenstrukturen und Algorithmen SS 2008 Blatt 5 AUFGABE 1 (6 Punkte): Nehmen wir an, Anfang bezeichne in einer normalen

Mehr

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

Wiederholung. Bäume sind zyklenfrei. Rekursive Definition: Baum = Wurzelknoten + disjunkte Menge von Kindbäumen. Wiederholung Baum: Gerichteter Graph, der die folgenden drei Bedingungen erfüllt: Es gibt einen Knoten, der nicht Endknoten einer Kante ist. (Dieser Knoten heißt Wurzel des Baums.) Jeder andere Knoten

Mehr

Berechnungsschemata: Funktion als Parameter abstrahiert Operation im Schema, wird bei Aufruf des Schemas konkretisiert

Berechnungsschemata: Funktion als Parameter abstrahiert Operation im Schema, wird bei Aufruf des Schemas konkretisiert 6. Funktionen als Daten, Übersicht Orthogonales Typsystem: Funktionen sind beliebig mit anderen Typen kombinierbar Notation für Funktionswerte (Lambda-Ausdruck): fn (z,k) => z*k Datenstrukturen mit Funktionen

Mehr

13. Bäume: effektives Suchen und Sortieren

13. Bäume: effektives Suchen und Sortieren Schwerpunkte Aufgabe und Vorteile von Bäumen 13. Bäume: effektives Suchen und Sortieren Java-Beispiele: Baum.java Traverse.java TraverseTest.java Sortieren mit Bäumen Ausgabealgorithmen: - Preorder - Postorder

Mehr

Informatik II, SS 2016

Informatik II, SS 2016 Informatik II - SS 2016 (Algorithmen & Datenstrukturen) Vorlesung 10 (27.5.2016) Binäre Suchbäume II Algorithmen und Komplexität Zusätzliche Dictionary Operationen Dictionary: Zusätzliche mögliche Operationen:

Mehr

1 Der Baum. Informatik I: Einführung in die Programmierung 11. Bäume. Bäume in der Informatik. Bäume in der Informatik - Definition.

1 Der Baum. Informatik I: Einführung in die Programmierung 11. Bäume. Bäume in der Informatik. Bäume in der Informatik - Definition. 1 Informatik I: Einführung in die Programmierung 11. Bäume e e Albert-Ludwigs-Universität Freiburg Bernhard Nebel 13. November 2015 13. November 2015 B. Nebel Info I 3 / 33 Bäume in der Informatik Bäume

Mehr

Grundlagen der Programmierung

Grundlagen der Programmierung Grundlagen der Programmierung Algorithmen und Datenstrukturen Die Inhalte der Vorlesung wurden primär auf Basis der angegebenen Literatur erstellt. Darüber hinaus sind viele Teile direkt aus der Vorlesung

Mehr

WS 2011/2012. RobertGiegerich. November 12, 2013

WS 2011/2012. RobertGiegerich. November 12, 2013 WS 2011/2012 Robert AG Praktische Informatik November 12, 2013 Haskell-Syntax: Ergänzungen Es gibt noch etwas bequeme Notation für Fallunterscheidungen, die wir bisher nicht benutzt haben. Bisher kennen

Mehr

Dynamische Mengen. Realisierungen durch Bäume

Dynamische Mengen. Realisierungen durch Bäume Dynamische Mengen Eine dynamische Menge ist eine Datenstruktur, die eine Menge von Objekten verwaltet. Jedes Objekt x trägt einen eindeutigen Schlüssel key[x]. Die Datenstruktur soll mindestens die folgenden

Mehr

Grundprinzipien der funktionalen Programmierung

Grundprinzipien der funktionalen Programmierung Grundprinzipien der funktionalen Programmierung Funktionen haben keine Seiteneffekte Eine Funktion berechnet einen Ausgabewert der nur von den Eingabewerten abhängt: 12 inputs + output 46 34 2 Nicht nur

Mehr

2 Sortieren. Beispiel: Es seien n = 8 und a = i : a i : ϕ(i) : a ϕ(i) :

2 Sortieren. Beispiel: Es seien n = 8 und a = i : a i : ϕ(i) : a ϕ(i) : 2 Sortieren Das Sortieren einer Datenfolge ist eines der am leichtesten zu verstehenden und am häufigsten auftretenden algorithmischen Probleme. In seiner einfachsten Form besteht das Problem darin, eine

Mehr

Funktionale Programmierung Grundlegende Datentypen

Funktionale Programmierung Grundlegende Datentypen Grundlegende Datentypen Prof. Dr. Oliver Braun Fakultät für Informatik und Mathematik Hochschule München Letzte Änderung: 06.11.2017 16:45 Inhaltsverzeichnis Typen........................................

Mehr

1. Probeklausur (Lösung) zu Programmierung 1 (WS 07/08)

1. Probeklausur (Lösung) zu Programmierung 1 (WS 07/08) Fachschaft Informatikstudiengänge Fachrichtung 6.2 Informatik Das Team der Bremser 1. Probeklausur (Lösung) zu Programmierung 1 (WS 07/08) http://fsinfo.cs.uni-sb.de Name Matrikelnummer Bitte öffnen Sie

Mehr

Sortierverfahren für Felder (Listen)

Sortierverfahren für Felder (Listen) Sortierverfahren für Felder (Listen) Generell geht es um die Sortierung von Daten nach einem bestimmten Sortierschlüssel. Es ist auch möglich, daß verschiedene Daten denselben Sortierschlüssel haben. Es

Mehr

1 Der Baum. Informatik I: Einführung in die Programmierung 11. Bäume. Bäume in der Informatik. Bäume in der Informatik - Definition.

1 Der Baum. Informatik I: Einführung in die Programmierung 11. Bäume. Bäume in der Informatik. Bäume in der Informatik - Definition. 1 Informatik I: Einführung in die Programmierung 11. Bäume e e Albert-Ludwigs-Universität Freiburg Bernhard Nebel 17. November 2017 17. November 2017 B. Nebel Info I 3 / 33 Bäume in der Informatik Bäume

Mehr

expr :: Expr expr = Mul (Add (Const 3) (Const 4)) (Div (Sub (Const 73) (Const 37)) (Const 6))

expr :: Expr expr = Mul (Add (Const 3) (Const 4)) (Div (Sub (Const 73) (Const 37)) (Const 6)) 1 - Korrektur 2 - Abstrakte Datentypen für arithmetische Ausdrücke Der Datentyp Wir beginnen zunächst mit dem algebraischen Datentyp für Ausdrücke. Hierfür definieren wir einen Konstruktor Number für Zahlen,

Mehr

Technische Universität München. Vorlesungsgrobstruktur: wo stehen wir, wie geht s weiter

Technische Universität München. Vorlesungsgrobstruktur: wo stehen wir, wie geht s weiter Vorlesungsgrobstruktur: wo stehen wir, wie geht s weiter Kapitel 7 Fortgeschrittene Datenstrukturen Motivation: Lineare Liste: Suchen eines Elements ist schnell O(log n) Einfügen eines Elements ist langsam

Mehr

Untere Schranke für allgemeine Sortierverfahren

Untere Schranke für allgemeine Sortierverfahren Untere Schranke für allgemeine Sortierverfahren Prinzipielle Frage: wie schnell kann ein Algorithmus (im worst case) überhaupt sein? Satz: Zum einer Folge von n Keys mit einem allgemeinen Sortierverfahren

Mehr

Suchen und Sortieren Sortieren. Heaps

Suchen und Sortieren Sortieren. Heaps Suchen und Heaps (Folie 245, Seite 63 im Skript) 3 7 21 10 17 31 49 28 14 35 24 42 38 Definition Ein Heap ist ein Binärbaum, der die Heapeigenschaft hat (Kinder sind größer als der Vater), bis auf die

Mehr

Funktionale Programmierung mit Haskell

Funktionale Programmierung mit Haskell Funktionale Programmierung mit Haskell Dr. Michael Savorić Hohenstaufen-Gymnasium (HSG) Kaiserslautern Version 20120622 Überblick Wichtige Eigenschaften Einführungsbeispiele Listenerzeugung und Beispiel

Mehr

Programmiertechnik II

Programmiertechnik II 2007 Martin v. Löwis Priority Queues and Heapsort 2007 Martin v. Löwis 2 Priority Queue Abstrakter Datentyp Inhalt: Elemente mit Priorität Operationen: Einfügen: Angabe des Elements und seiner Priorität

Mehr

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

Heapsort / 1 A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] Heapsort / 1 Heap: Ein Array heißt Heap, falls A [i] A [2i] und A[i] A [2i + 1] (für 2i n bzw. 2i + 1 n) gilt. Beispiel: A[1] A[2] A[3] A[4] A[5] A[6] A[7] A[8] Heapsort / 2 Darstellung eines Heaps als

Mehr

Informatik II Prüfungsvorbereitungskurs

Informatik II Prüfungsvorbereitungskurs Informatik II Prüfungsvorbereitungskurs Tag 4, 23.6.2016 Giuseppe Accaputo g@accaputo.ch 1 Programm für heute Repetition Datenstrukturen Unter anderem Fragen von gestern Point-in-Polygon Algorithmus Shortest

Mehr

Tutoraufgabe 1 (Sortieren): Lösung: Datenstrukturen und Algorithmen SS14 Lösung - Übung 4

Tutoraufgabe 1 (Sortieren): Lösung: Datenstrukturen und Algorithmen SS14 Lösung - Übung 4 Prof. aa Dr. E. Ábrahám Datenstrukturen und Algorithmen SS Lösung - Übung F. Corzilius, S. Schupp, T. Ströder Tutoraufgabe (Sortieren): a) Sortieren Sie das folgende Array durch Anwendung des Selectionsort-Algorithmus.

Mehr

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 7 (Kapitel 7)

Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 7 (Kapitel 7) Fachrichtung 6.2 Informatik Universität des Saarlandes Tutorenteam der Vorlesung Programmierung 1 Programmierung 1 (Wintersemester 2012/13) Lösungsblatt 7 (Kapitel 7) Hinweis: Dieses Übungsblatt enthält

Mehr

JAVA - Suchen - Sortieren

JAVA - Suchen - Sortieren Übungen Informatik I JAVA - Suchen - Sortieren http://www.fbi-lkt.fh-karlsruhe.de/lab/info01/tutorial Übungen Informatik 1 Folie 1 Inhalt Suchen/Sortieren binary search mergesort bubblesort Übungen Informatik

Mehr

Graphdurchmusterung, Breiten- und Tiefensuche

Graphdurchmusterung, Breiten- und Tiefensuche Prof. Thomas Richter 18. Mai 2017 Institut für Analysis und Numerik Otto-von-Guericke-Universität Magdeburg thomas.richter@ovgu.de Material zur Vorlesung Algorithmische Mathematik II am 18.05.2017 Graphdurchmusterung,

Mehr

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v)

Der linke Teilbaum von v enthält nur Schlüssel < key(v) und der rechte Teilbaum enthält nur Schlüssel > key(v) Ein Baum T mit Knotengraden 2, dessen Knoten Schlüssel aus einer total geordneten Menge speichern, ist ein binärer Suchbaum (BST), wenn für jeden inneren Knoten v von T die Suchbaumeigenschaft gilt: Der

Mehr

Inhaltsverzeichnis. Teil 1 Grundlagen 21. Teil 2 Datenstrukturen 85

Inhaltsverzeichnis. Teil 1 Grundlagen 21. Teil 2 Datenstrukturen 85 Inhaltsverzeichnis Vorwort 13 Umfang 14 Einsatz als Unterrichtsmittel 14 Algorithmen mit Praxisbezug 15 Programmiersprache 16 Danksagung 17 Vorwort des Java-Beraters 18 Hinweise zu den Übungen 19 Teil

Mehr

Frage, Fragen und nochmals Fragen

Frage, Fragen und nochmals Fragen Frage, Fragen und nochmals Fragen Berthold Hoffmann Universität Bremen and DFKI Bremen hof@informatik.uni-bremen.de In diesem Text stehen einige Fragen, die man sich zu den Folien der Veranstaltung Funktionales

Mehr

8.1.3 Operation Build-Max-Heap Operation zur Konstruktion eines Heaps Eingabe: Feld A[1..n], n = länge(a) BUILD-MAX-HEAP (A)

8.1.3 Operation Build-Max-Heap Operation zur Konstruktion eines Heaps Eingabe: Feld A[1..n], n = länge(a) BUILD-MAX-HEAP (A) Stand der Vorlesung: Datenstruktur Heap: fast vollständiger Binärbaum MaxHeap: sortierter Heap, größtes Element an Wurzel Sortierverfahren: HeapSort: Sortieren eines Feldes A[1.. n] Idee: in place: Feld

Mehr

Datenstrukturen und Algorithmen 2. Klausur SS 2001

Datenstrukturen und Algorithmen 2. Klausur SS 2001 UNIVERSITÄT PADERBORN FACHBEREICH 7 (MATHEMATIK INFORMATIK) Datenstrukturen und Algorithmen 2. Klausur SS 200 Lösungsansätze Dienstag, 8. September 200 Name, Vorname:...................................................

Mehr

Übung Algorithmen und Datenstrukturen

Übung Algorithmen und Datenstrukturen Übung Algorithmen und Datenstrukturen Sommersemester 217 Patrick Schäfer, Humboldt-Universität zu Berlin Agenda: Graphen, Suchbäume, AVL Bäume Heute: Graphen und Bäume Binäre Suchbäume AVL-Bäume Nächste

Mehr

Technische Universität München

Technische Universität München Stand der Vorlesung: Datenstruktur Heap: fast vollständiger Binärbaum MaxHeap: sortierter Heap, größtes Element an Wurzel Sortierverfahren: HeapSort: Sortieren eines Feldes A[1.. n] Idee: in place: Feld

Mehr

Algorithmen und Datenstrukturen 1

Algorithmen und Datenstrukturen 1 Algorithmen und Datenstrukturen 1 7. Vorlesung Peter F. Stadler Universität Leipzig Institut für Informatik studla@informatik.uni-leipzig.de aufbauend auf den Kursen der letzten Jahre von E. Rahm, G. Heyer,

Mehr

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen Algorithmen und Datenstrukturen 11. Übung Verkettete Listen, Sortieren Insertionsort, Mergesort, Radixsort, Quicksort Clemens Lang Übungen zu AuD 19. Januar 2010 Clemens Lang (Übungen zu AuD) Algorithmen

Mehr

3. Übungsblatt zu Algorithmen I im SoSe 2017

3. Übungsblatt zu Algorithmen I im SoSe 2017 Karlsruher Institut für Technologie Prof. Dr. Jörn Müller-Quade Institut für Theoretische Informatik Björn Kaidel, Sebastian Schlag, Sascha Witt 3. Übungsblatt zu Algorithmen I im SoSe 2017 http://crypto.iti.kit.edu/index.php?id=799

Mehr

Algorithmen und Datenstrukturen Balancierte Suchbäume

Algorithmen und Datenstrukturen Balancierte Suchbäume Algorithmen und Datenstrukturen Balancierte Suchbäume Matthias Teschner Graphische Datenverarbeitung Institut für Informatik Universität Freiburg SS 12 Überblick Einführung Einfügen und Löschen Einfügen

Mehr

Informatik-Seminar Thema 6: Bäume

Informatik-Seminar Thema 6: Bäume Informatik-Seminar 2003 - Thema 6: Bäume Robin Brandt 14. November 2003 1 Robin Brandt Informatik-Seminar 2003 - Thema 6: Bäume Übersicht Definition Eigenschaften Operationen Idee Beispiel Datendefinition

Mehr

ContainerDatenstrukturen. Große Übung 4

ContainerDatenstrukturen. Große Übung 4 ContainerDatenstrukturen Große Übung 4 Aufgabenstellung Verwalte Kollektion S von n Objekten Grundaufgaben: Iterieren/Auflistung Suche nach Objekt x mit Wert/Schlüssel k Füge ein Objekt x hinzu Entferne

Mehr

Algorithmen und Datenstrukturen

Algorithmen und Datenstrukturen Algorithmen und Datenstrukturen Dynamische Datenobjekte Pointer/Zeiger, Verkettete Liste Eigene Typdefinitionen 1 Zeigeroperatoren & und * Ein Zeiger ist die Speicheradresse irgendeines Objektes. Eine

Mehr

Tutoraufgabe 1 (Sortieralgorithmus):

Tutoraufgabe 1 (Sortieralgorithmus): Prof. aa Dr. Ir. Joost-Pieter Katoen Datenstrukturen und Algorithmen SS Tutoriumslösung - Übung 4 (Abgabe 2..2) Christian Dehnert, Friedrich Gretz, Benjamin Kaminski, Thomas Ströder Tutoraufgabe (Sortieralgorithmus):

Mehr

Übungsblatt 1. f(n) = f(n) = O(g(n)) g(n) = O(f(n)) Zeigen oder widerlegen Sie: 3 n = Θ(2 n ) Aufgabe 1.2 Gegeben sei die folgende Funktion:

Übungsblatt 1. f(n) = f(n) = O(g(n)) g(n) = O(f(n)) Zeigen oder widerlegen Sie: 3 n = Θ(2 n ) Aufgabe 1.2 Gegeben sei die folgende Funktion: Übungsblatt 1 Aufgabe 1.1 Beweisen oder widerlegen Sie, dass für die im Folgenden definierte Funktion f(n) die Beziehung f(n) = Θ(n 4 ) gilt. Beachten Sie, dass zu einem vollständigen Beweis gegebenenfalls

Mehr

Motivation Binäre Suchbäume

Motivation Binäre Suchbäume Kap..: Binäre Suchbäume Professor Dr. Lehrstuhl für Algorithm Engineering, LS Fakultät für Informatik, TU Dortmund Zusätzliche Lernraumbetreuung Morteza Monemizadeh: Jeden Montag von :00 Uhr-:00 Uhr in

Mehr

Tag 7. Pattern Matching und eigene Datentypen

Tag 7. Pattern Matching und eigene Datentypen Tag 7 Pattern Matching und eigene Datentypen Heute werden wir eine Technik kennenlernen, die dafür sorgt, daß wir sehr viel übersichtlichere und kürzere Programme schreiben können. Als Überleitung auf

Mehr