Foliensatz 7 (4 auf 1)

Werbung
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
3. Funktionales Programmieren
Unterabschnitt 3.1.6
3.1 Grundkonzepte funktionaler Programmierung
Begriffsklärung: (Modulsystem)
Ein Programmmodul fasst mehrere Deklarationen zusammen und
stellt sie unter einem Namen zur Verfügung.
Module
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
Ein Programmmodul sollte Programmierern eine Modul-Schnittstelle
bereitstellen, die unabhängig von der Implementierung dokumentiert
und benutzbar ist.
317
©Arnd Poetzsch-Heffter
3.1 Grundkonzepte funktionaler Programmierung
TU Kaiserslautern
3. Funktionales Programmieren
Module in Haskell
318
3.1 Grundkonzepte funktionaler Programmierung
Begriffsklärung: (Programm, die 2.)
Vereinfacht dargestellt, hat ein Haskell-Modul die Form:
module <Modulname > ( <kommagetrennte Liste
exportierter Programmelemente >
) where
import <Modul1 >
...
import <Moduln >
<Deklarationen des Moduls >
Ein Haskell-Programm (vgl. F. 211) besteht aus einer Menge von
Modulen, wobei ein Modul
• den Name Main haben muss und
• in diesem Modul der Name main deklariert sein muss.
Die Programmausführung beginnt mit der Ausführung der Deklaration
von main.
Dabei gilt:
• Die Liste der importierten und exportierten Programmelemente
kann leer sein.
• Fehlt die Exportliste einschließlich der Klammern, werden alle in
dem Modul deklarierten Programmelemente exportiert.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
319
©Arnd Poetzsch-Heffter
TU Kaiserslautern
320
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
3. Funktionales Programmieren
Beispiel: (Haskell-Module)
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Haskell-Module) (2)
module Breg where
module Alster where
import Alster
avalue = 7;
data Broterwerb = Designer | Maler | Bildhauer
data Art = Painting | Design | Sculpture
beruf
beruf
beruf
beruf
ache Design = False
ache _
= True
:: Art ->
Design
Painting
Sculpture
Broterwerb
= Designer
= Maler
= Bildhauer
bflag = (ache Painting )
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
321
3.1 Grundkonzepte funktionaler Programmierung
TU Kaiserslautern
3. Funktionales Programmieren
Beispiel: (Haskell-Module) (3)
322
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Schnittstelle)
module Environment (Env , emptyEnv , insertI , insertB ,
lookUp ,
delete , IBValue (Intv , Boolv , None) )
where
module Main where
import Breg
emptyEnv :: Env
-- leere Bezeichnerumbegung
main = print bflag
insertI :: String -> Int -> Env -> Env
-- ( insertI bez i e) traegt die Bindung (bez ,i)
-- in die Umgebung e ein
Beachte:
Programmelemente aus Alster, z.B. avalue, sind nicht sichtbar in
Modul Main.
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
TU Kaiserslautern
insertB :: String -> Bool -> Env -> Env
-- ( insertB bez b e) traegt die Bindung (bez ,b)
-- in die Umgebung e ein
323
©Arnd Poetzsch-Heffter
TU Kaiserslautern
324
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
3. Funktionales Programmieren
Beispiel: (Modul-Schnittstelle) (2)
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Implementierung)
-- Modulimplementierung ( Fortsetzung von Environment )
data IBValue = Intv Int
| Boolv Bool
| None
lookUp :: String -> Env -> IBValue
-- ( lookUp bez e) liefert den Wert v der ersten
gefundenen
-- Bindung (bez ,v) mit Bezeichner bez
type Env = [ (String , IBValue ) ]
delete :: String -> Env -> Env
-- ( delete bez e) loescht alle Bindungen (bez ,_)
-- mit Bezeichner bez
emptyEnv = []
insertI bez i e = (bez ,Intv i):e
insertB bez b e = (bez ,Boolv b):e
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
325
©Arnd Poetzsch-Heffter
3.1 Grundkonzepte funktionaler Programmierung
TU Kaiserslautern
3. Funktionales Programmieren
Beispiel: (Modul-Implementierung) (2)
326
3.1 Grundkonzepte funktionaler Programmierung
Unterabschnitt 3.1.7
lookUp bez []
= None
lookUp bez ((bz ,val):e)
| bez == bz = val
| otherwise = lookUp bez e
Zusammenfassung von 3.1
delete bez []
= []
delete bez ((bz ,val):e)
| bez == bz = delete bez e
| otherwise = (bz ,val):( delete bez e)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
327
©Arnd Poetzsch-Heffter
TU Kaiserslautern
328
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
3. Funktionales Programmieren
Zusammenfassung von 3.1
3.2 Algorithmen auf Listen und Bäumen
Abschnitt 3.2
Begriffe und Sprachmittel wie Ausdruck, Bezeichner, Vereinbarung,
Wert, Typ, Muster, Modul, . . . .
Wichtige Programmier- und Modellierungskonzepte:
Algorithmen auf Listen und Bäumen
• Basisdatenstrukturen
• rekursive Funktionen
• rekursive Datentypen (insbesondere Listen)
• Ein- und Ausgabe
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
329
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
Algorithmen auf Listen und Bäumen
330
3.2 Algorithmen auf Listen und Bäumen
Lernziele:
• Intuitiver Algorithmusbegriff
• Kenntnis wichtiger/klassischer Algorithmen und
Algorithmenklassen
Sortieren und Suchen sind elementare Aufgaben, die in den meisten
Programmen anfallen.
• Zusammenhang Algorithmus und Datenstruktur
Verfahren zum Suchen und Sortieren spielen eine zentrale Rolle in der
Algorithmik.
• Wege vom Problem zum Algorithmus
• Implementierungstechniken für Datenstrukturen und Algorithmen
(vom Algorithmus zum Programm)
Bemerkung:
Wir führen in den Bereich Algorithmen und Datenstrukturen
ausgehend vom Problem ein. Andere Möglichkeit wäre gemäß der
benutzten Datenstrukturen (Listen, Bäume, etc.).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
331
©Arnd Poetzsch-Heffter
TU Kaiserslautern
332
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
Unterabschnitt 3.2.1
Sortieren
Sortieren ist eine Standardaufgabe, die Teil vieler speziellerer,
umfassenderer Aufgaben ist.
Sortieren
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
Untersuchungen zeigen, dass „mehr als ein Viertel der kommerziell
verbrauchten Rechenzeit auf Sortiervorgänge entfällt“
(Ottmann, Widmayer: Algorithmen und Datenstrukturen, Kap. 2).
333
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
Begriffsklärung: (Sortierproblem)
334
3.2 Algorithmen auf Listen und Bäumen
Bemerkung:
Gegeben ist eine Folge s1 , . . . , sN von sogenannten Datensätzen.
Offene Aspekte der Formulierung des Sortierproblem:
Jeder Satz sj hat einen Schlüssel kj . Wir gehen davon aus, dass die
Schlüssel ganzzahlig sind.
• Was heißt, eine Folge ist „gegeben“?
Aufgabe des Sortierproblems ist es, eine Permutation π zu finden, so
dass die Umordnung der Sätze gemäß π folgende Reihenfolge auf den
Schlüsseln ergibt:
• Ist der Bereich der Schlüssel bekannt?
• Welche Operationen stehen zur Verfügung, um π zu bestimmen?
• Was genau heißt „Umordnung“?
kπ(1) ≤ kπ(2) ≤ · · · ≤ kπ(N)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
335
©Arnd Poetzsch-Heffter
TU Kaiserslautern
336
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
Aufgabenstellung:
Aufgabenstellung: (2)
Wir benutzen Datensätze folgenden Typs
Entwickle eine Funktion
type Dataset = (Int , String )
sort :: [ Dataset ] -> [ Dataset ]
mit Vergleichsfunktion:
so dass das Ergebnis von sort xl für alle Eingaben xl aufsteigend
sortiert ist und die gleichen Elemente enthält wie xl (mehrere Einträge
mit gleichem Schlüssel sind nicht ausgeschlossen).
leq:: Dataset -> Dataset -> Bool
leq (kx , dx) (ky , dy) = (kx <=ky)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
337
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
Aufgabenstellung: (3)
338
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Auswahl (selection sort)
Wir betrachten:
• Sortieren durch Auswahl (engl. selection sort)
Algorithmische Idee:
• Sortieren durch Einfügen (engl. insertion sort)
• Entferne einen minimalen Eintrag min aus der Liste.
• Bubblesort
• Sortiere die Liste, aus der min entfernt wurde.
• Füge min als ersten Element an die sortierte Liste an.
• Sortieren durch rekursives Teilen (quick sort)
• Sortieren durch Mischen (merge sort)
• Heapsort
©Arnd Poetzsch-Heffter
TU Kaiserslautern
339
©Arnd Poetzsch-Heffter
TU Kaiserslautern
340
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Auswahl (selection sort) (2)
Sortieren durch Auswahl (selection sort) (3)
select :: Dataset -> [ Dataset ] -> Dataset
-- Hilfsfunktion : liefert einen minimalen Eintrag der
-- Liste bzw. x, falls x minimal
delete :: Dataset -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : loescht ein Vorkommen von x aus der
-- Liste , falls solches vorhanden
select x []
= x
select x (y:yl) = if x `leq` y then select x yl
else select y yl
delete x []
= []
delete x (y:yl) = if (x==y) then
else
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
341
3.2 Algorithmen auf Listen und Bäumen
342
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Einfügen (insertion sort)
selectionsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Auswahl
-mnm: ein minimaler Eintrag in Liste xl
-rest: die Liste xl ohne min
Algorithmische Idee:
• Sortiere zunächst den Rest der Liste.
selectionsort []
= []
selectionsort (x:xl) =
let mnm = select x xl
rest = delete mnm (x:xl)
in
mnm : ( selectionsort rest)
TU Kaiserslautern
TU Kaiserslautern
3. Funktionales Programmieren
Sortieren durch Auswahl (selection sort) (4)
©Arnd Poetzsch-Heffter
©Arnd Poetzsch-Heffter
yl
y:( delete x yl)
• Füge dann den ersten Eintrag in die sortierte Liste ein.
343
©Arnd Poetzsch-Heffter
TU Kaiserslautern
344
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Einfügen (insertion sort) (2)
Sortieren durch Einfügen (insertion sort) (3)
insert :: Dataset -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : fuegt Argument in sortierte Liste ein
-- Ergebnis : sortierte Liste
insertionsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Einfuegen
insert x []
=
insert x (y:yl) =
insertionsort []
= []
insertionsort (x:xl) = insert x ( insertionsort xl)
©Arnd Poetzsch-Heffter
[x]
if (x `leq` y)
then x : (y:yl)
else y : ( insert x yl)
TU Kaiserslautern
3. Funktionales Programmieren
345
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bubblesort
Bubblesort (2)
Algorithmische Idee:
bubble :: [ Dataset ] -> Dataset -> [ Dataset ]
-> ([ Dataset ], Dataset )
-- Hilfsfunktion : liefert einen maximalen Eintrag der
-- Liste und die Liste ohne den maximalen Eintrag
• Schiebe einen Eintrag nach rechts heraus:
I Beginne dazu mit dem ersten Eintrag x.
I Wenn Schieben von x auf einen gleichen oder größeren Eintrag y
stößt, schiebe y weiter.
I Ergebnis: maximaler Eintrag mxe und Liste ohne mxe
bubble rl x []
= (rl ,x)
bubble rl x (y:yl) = if (x `leq` y)
then bubble (rl ++[x]) y yl
else bubble (rl ++[y]) x yl
• Sortiere die Liste ohne mxe und hänge mxe an.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
346
347
©Arnd Poetzsch-Heffter
TU Kaiserslautern
348
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
Bubblesort (3)
3.2 Algorithmen auf Listen und Bäumen
Quicksort: Sortieren durch Teilen
Algorithmische Idee:
• Wähle einen beliebigen Datensatz mit Schlüssel k aus, das
bubblesort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Herausschieben der maximalen
-Elemente
sogenannte Pivotelement.
• Teile die Liste in zwei Teile:
I 1. Teil enthält alle Datensätze mit Schlüsseln < k
I 2. Teil enthält die Datensätze mit Schlüsseln ≥ k
bubblesort []
= []
bubblesort (x:xl) = let (rl ,mxe) = bubble [] x xl
in ( bubblesort rl)++[ mxe]
• Wende quicksort rekursiv auf die Teillisten an.
• Hänge die resultierenden Listen und das Pivotelement zusammen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
349
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Quicksort: Sortieren durch Teilen (2)
Quicksort: Sortieren durch Teilen (3)
split :: Dataset -> [ Dataset ] -> ([ Dataset ],[ Dataset ])
-- Hilfsfkt .: teilt Liste in zwei Listen (below ,above)
-- below: alle Elemente in kleiner p
-- above: alle Elemente groesser gleich p
qsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren nach der Strategie ``Teile und Herrsche ’’
split p
split p
let
in
qsort []
= []
qsort (p:rest) = let (below ,above) = split p rest
in (qsort below) ++ [p] ++ (qsort above )
[]
= ([] ,[])
(x:xr) =
(blw ,abv) = split p xr
if p `leq` x then (blw ,x:abv)
else (x:blw ,abv)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
350
351
©Arnd Poetzsch-Heffter
TU Kaiserslautern
352
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
3. Funktionales Programmieren
Bemerkung:
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Mischen:
Algorithmische Idee:
• Hat die Liste mehr als ein Element, berechne die Länge der Liste
div 2 (halfsize).
Quicksort ist ein typischer Algorithmus gemäß der
Divide-and-Conquer-Strategie:
• Teile die Liste in zwei Teile der Länge halfsize (+1).
• Zerlege das Problem in Teilprobleme.
• Sortiere die Teile.
• Wende den Algorithmus auf die Teilprobleme an.
• Mische die Teile zusammen.
• Füge die Ergebnisse zusammen.
Bemerkung:
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.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
3. Funktionales Programmieren
353
©Arnd Poetzsch-Heffter
3.2 Algorithmen auf Listen und Bäumen
TU Kaiserslautern
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bemerkung:
Bemerkung: (2)
merge :: [ Dataset ] -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : mischt zwei sortierte Listen
-- zu einer sortierten Liste zusammen
mergesort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Mischen
-halfsize : Haelfte der Listenlaenge
-front :
Vordere Haelfte der Liste
-back :
Hintere Haelfte der Liste
merge
merge
merge
merge
[] []
[] yl
xl []
(x:xl) (y:yl)
©Arnd Poetzsch-Heffter
=
=
=
=
mergesort []
= []
mergesort (x:[]) = [x]
mergesort xl
=
let halfsize = ( length xl) `div` 2
front
= take halfsize xl
back
= drop halfsize xl
in
merge ( mergesort front) ( mergesort back)
[]
yl
xl
if (x `leq` y)
then x : (merge xl (y:yl))
else y : (merge (x:xl) yl)
TU Kaiserslautern
354
355
©Arnd Poetzsch-Heffter
TU Kaiserslautern
356
Herunterladen