1 auf 1

Werbung
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Unterabschnitt 3.1.6
Module
©Arnd Poetzsch-Heffter
TU Kaiserslautern
317
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Begriffsklärung: (Modulsystem)
Ein Programmmodul fasst mehrere Deklarationen zusammen und
stellt sie unter einem Namen zur Verfügung.
Ein Programmmodul sollte Programmierern eine Modul-Schnittstelle
bereitstellen, die unabhängig von der Implementierung dokumentiert
und benutzbar ist.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
318
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Module in Haskell
Vereinfacht dargestellt, hat ein Haskell-Modul die Form:
module <Modulname > ( <kommagetrennte Liste
exportierter Programmelemente >
) where
import <Modul1 >
...
import <Moduln >
<Deklarationen des Moduls >
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
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Begriffsklärung: (Programm, die 2.)
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.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
320
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Haskell-Module)
module Alster where
avalue = 7;
data Art = Painting | Design | Sculpture
ache Design = False
ache _
= True
©Arnd Poetzsch-Heffter
TU Kaiserslautern
321
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Haskell-Module) (2)
module Breg where
import Alster
data Broterwerb = Designer | Maler | Bildhauer
beruf
beruf
beruf
beruf
:: Art ->
Design
Painting
Sculpture
Broterwerb
= Designer
= Maler
= Bildhauer
bflag = (ache Painting )
©Arnd Poetzsch-Heffter
TU Kaiserslautern
322
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Haskell-Module) (3)
module Main where
import Breg
main = print bflag
Beachte:
Programmelemente aus Alster, z.B. avalue, sind nicht sichtbar in
Modul Main.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
323
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Schnittstelle)
module Environment (Env , emptyEnv , insertI , insertB ,
lookUp ,
delete , IBValue (Intv , Boolv , None) )
where
emptyEnv :: Env
-- leere Bezeichnerumbegung
insertI :: String -> Int -> Env -> Env
-- ( insertI bez i e) traegt die Bindung (bez ,i)
-- in die Umgebung e ein
insertB :: String -> Bool -> Env -> Env
-- ( insertB bez b e) traegt die Bindung (bez ,b)
-- in die Umgebung e ein
©Arnd Poetzsch-Heffter
TU Kaiserslautern
324
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Schnittstelle) (2)
lookUp :: String -> Env -> IBValue
-- ( lookUp bez e) liefert den Wert v der ersten
gefundenen
-- Bindung (bez ,v) mit Bezeichner bez
delete :: String -> Env -> Env
-- ( delete bez e) loescht alle Bindungen (bez ,_)
-- mit Bezeichner bez
©Arnd Poetzsch-Heffter
TU Kaiserslautern
325
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Implementierung)
-- Modulimplementierung ( Fortsetzung von Environment )
data IBValue = Intv Int
| Boolv Bool
| None
type Env = [ (String , IBValue ) ]
emptyEnv = []
insertI bez i e = (bez ,Intv i):e
insertB bez b e = (bez , Boolv b):e
©Arnd Poetzsch-Heffter
TU Kaiserslautern
326
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Beispiel: (Modul-Implementierung) (2)
lookUp bez []
= None
lookUp bez ((bz ,val):e)
| bez == bz = val
| otherwise = lookUp bez e
delete bez []
= []
delete bez ((bz ,val):e)
| bez == bz = delete bez e
| otherwise = (bz ,val):( delete bez e)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
327
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Unterabschnitt 3.1.7
Zusammenfassung von 3.1
©Arnd Poetzsch-Heffter
TU Kaiserslautern
328
3. Funktionales Programmieren
3.1 Grundkonzepte funktionaler Programmierung
Zusammenfassung von 3.1
Begriffe und Sprachmittel wie Ausdruck, Bezeichner, Vereinbarung,
Wert, Typ, Muster, Modul, . . . .
Wichtige Programmier- und Modellierungskonzepte:
• Basisdatenstrukturen
• rekursive Funktionen
• rekursive Datentypen (insbesondere Listen)
• Ein- und Ausgabe
©Arnd Poetzsch-Heffter
TU Kaiserslautern
329
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Abschnitt 3.2
Algorithmen auf Listen und Bäumen
©Arnd Poetzsch-Heffter
TU Kaiserslautern
330
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
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.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
331
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
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)
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
332
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Unterabschnitt 3.2.1
Sortieren
©Arnd Poetzsch-Heffter
TU Kaiserslautern
333
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren
Sortieren ist eine Standardaufgabe, die Teil vieler speziellerer,
umfassenderer 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).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
334
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Begriffsklärung: (Sortierproblem)
Gegeben ist eine Folge s1 , . . . , sN von sogenannten Datensätzen.
Jeder Satz sj hat einen Schlüssel kj . 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äß π folgende Reihenfolge auf den
Schlüsseln ergibt:
kπ(1) ≤ kπ(2) ≤ · · · ≤ kπ(N)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
335
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bemerkung:
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“?
©Arnd Poetzsch-Heffter
TU Kaiserslautern
336
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Aufgabenstellung:
Wir benutzen Datensätze folgenden Typs
type Dataset = (Int , String )
mit Vergleichsfunktion:
leq:: Dataset -> Dataset -> Bool
leq (kx , dx) (ky , dy) = (kx <=ky)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
337
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Aufgabenstellung: (2)
Entwickle eine Funktion
sort :: [ Dataset ] -> [ Dataset ]
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).
©Arnd Poetzsch-Heffter
TU Kaiserslautern
338
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Aufgabenstellung: (3)
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
©Arnd Poetzsch-Heffter
TU Kaiserslautern
339
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
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.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
340
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Auswahl (selection sort) (2)
select :: Dataset -> [ Dataset ] -> Dataset
-- Hilfsfunktion : liefert einen minimalen Eintrag der
-- Liste bzw. x, falls x minimal
select x []
= x
select x (y:yl) = if x `leq` y then select x yl
else select y yl
©Arnd Poetzsch-Heffter
TU Kaiserslautern
341
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Auswahl (selection sort) (3)
delete :: Dataset -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : loescht ein Vorkommen von x aus der
-- Liste , falls solches vorhanden
delete x []
= []
delete x (y:yl) = if (x==y) then
else
©Arnd Poetzsch-Heffter
TU Kaiserslautern
yl
y:( delete x yl)
342
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Auswahl (selection sort) (4)
selectionsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Auswahl
-mnm: ein minimaler Eintrag in Liste xl
-rest: die Liste xl ohne min
selectionsort []
= []
selectionsort (x:xl) =
let mnm = select x xl
rest = delete mnm (x:xl)
in
mnm : ( selectionsort rest)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
343
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
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.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
344
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Einfügen (insertion sort) (2)
insert :: Dataset -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : fuegt Argument in sortierte Liste ein
-- Ergebnis : sortierte Liste
insert x []
=
insert x (y:yl) =
©Arnd Poetzsch-Heffter
[x]
if (x `leq` y)
then x : (y:yl)
else y : ( insert x yl)
TU Kaiserslautern
345
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Sortieren durch Einfügen (insertion sort) (3)
insertionsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Einfuegen
insertionsort []
= []
insertionsort (x:xl) = insert x ( insertionsort xl)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
346
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bubblesort
Algorithmische Idee:
• 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
• Sortiere die Liste ohne mxe und hänge mxe an.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
347
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bubblesort (2)
bubble :: [ Dataset ] -> Dataset -> [ Dataset ]
-> ([ Dataset ], Dataset )
-- Hilfsfunktion : liefert einen maximalen Eintrag der
-- Liste und die Liste ohne den maximalen Eintrag
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
©Arnd Poetzsch-Heffter
TU Kaiserslautern
348
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bubblesort (3)
bubblesort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Herausschieben der maximalen
-Elemente
bubblesort []
= []
bubblesort (x:xl) = let (rl ,mxe) = bubble [] x xl
in ( bubblesort rl)++[ mxe]
©Arnd Poetzsch-Heffter
TU Kaiserslautern
349
3. Funktionales Programmieren
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
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
• Wende quicksort rekursiv auf die Teillisten an.
• Hänge die resultierenden Listen und das Pivotelement zusammen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
350
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Quicksort: Sortieren durch Teilen (2)
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
split p
split p
let
in
[]
= ([] ,[])
(x:xr) =
(blw ,abv) = split p xr
if p `leq` x then (blw ,x:abv)
else (x:blw ,abv)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
351
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Quicksort: Sortieren durch Teilen (3)
qsort :: [ Dataset ] -> [ Dataset ]
-- Sortieren nach der Strategie ``Teile und Herrsche ’’
qsort []
= []
qsort (p:rest) = let (below , above ) = split p rest
in ( qsort below ) ++ [p] ++ ( qsort above )
©Arnd Poetzsch-Heffter
TU Kaiserslautern
352
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bemerkung:
Quicksort ist ein typischer Algorithmus gemäß der
Divide-and-Conquer-Strategie:
• Zerlege das Problem in Teilprobleme.
• Wende den Algorithmus auf die Teilprobleme an.
• Füge die Ergebnisse zusammen.
©Arnd Poetzsch-Heffter
TU Kaiserslautern
353
3. Funktionales Programmieren
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).
• Teile die Liste in zwei Teile der Länge halfsize (+1).
• Sortiere die Teile.
• Mische die Teile 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
354
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bemerkung:
merge :: [ Dataset ] -> [ Dataset ] -> [ Dataset ]
-- Hilfsfunktion : mischt zwei sortierte Listen
-- zu einer sortierten Liste zusammen
merge
merge
merge
merge
[] []
[] yl
xl []
(x:xl) (y:yl)
©Arnd Poetzsch-Heffter
=
=
=
=
[]
yl
xl
if (x `leq` y)
then x : ( merge xl (y:yl))
else y : ( merge (x:xl) yl)
TU Kaiserslautern
355
3. Funktionales Programmieren
3.2 Algorithmen auf Listen und Bäumen
Bemerkung: (2)
mergesort :: [ Dataset ] -> [ Dataset ]
-- Sortieren durch Mischen
-halfsize : Haelfte der Listenlaenge
-front :
Vordere Haelfte der Liste
-back :
Hintere Haelfte der Liste
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)
©Arnd Poetzsch-Heffter
TU Kaiserslautern
356
Herunterladen