1 / 17

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage: http://info1.marcwagner.info. Dienstag, den 08.04.03 Kapitel 5 Listen. 5.1 Listen als mathematische Objekte. Listen stellen eine endliche Folge von Objekten dar. Listendarstellung :.

erin-lucas
Download Presentation

WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. WS 2002/2003 Programmierung 1 - Repetitorium Andreas Augustin und Marc Wagner Homepage: http://info1.marcwagner.info

  2. Dienstag, den 08.04.03 Kapitel 5 Listen

  3. 5.1 Listen als mathematische Objekte Listen stellen eine endliche Folge von Objekten dar. Listendarstellung : • Die leere Folge wird als leeres Tupel dargestellt. • Eine nichtleere Folge x1,...,xn wird als Paar, das aus x1 und der • Listendarstellung der Folge x2,...,xn besteht, dargestellt. Beispiele : < > < > < > < > 3 < > 1 < > 2 < > 2 < > 3 < > 3 < > <2,<3,< >>> < > <3,< >> <1,<2,<3,< >>>> [ ] [3] [2,3] [1,2,3]

  4. 5.1 Listen als mathematische Objekte Bei einer nichtleeren Liste <x,xs> bezeichnet man x als den Kopf und xs als den Rumpf der Liste. Sei X eine Menge. Eine Liste heißt Liste über X, wenn alle ihre Elemente Elemente der Menge X sind. Die Listen über X lassen sich mit zwei Regeln konstruieren : • Das leere Tupel ist eine Liste über X. • Wenn x  X und xs eine Liste über X ist, dann ist <x,xs> eine Liste über X. [x1,...,xm] @ [y1,...,yn] = [x1,..,xm,y1,...,yn] Die Länge einer Liste xs bezeichnen wir mit |xs|. |[x1,...,xn]| = n |xs@ys| = |xs| + |ys| Die leere Liste [ ] bezeichnet man als nil. Für eine nichtleere Liste <x,xs> schreiben wir auch x::xs (lies: x cons xs). cons klammert nach rechts ⇒ x::(y::xs) = x::y::xs

  5. 5.2 Listen in Standard ML SML stellt für jeden Typ t einen Listentyp t list zur Verfügung. Die Werte dieses Typs sind alle Listen, die über Werten des Typs t gebildet werden. [ 1 , 2 , 3 ] Typ: int list Konstruktion: 1 :: ( 2 :: ( 3 :: nil ) ) [ 1.0 , 2.0 , 3.0 ] Typ: real list Konstruktion: 1.0 :: ( 2.0 :: ( 3.0 :: nil ) ) [ [ 2 , 3 ] , [ ] ] Typ: int list list Konstruktion: ( 2 :: ( 3 :: nil ) ) :: ( ( nil ) :: nil ) Der cons-Konstruktor klammert nach rechts : e1 :: e2 :: e3 = e1 :: ( e2 :: e3 ) Beispiele : 1 :: 2 :: 3 :: nil = 1 :: [ 2 , 3 ] = [ 1 , 2 , 3 ] op::( 2 , nil ) = 2 :: nil = [ 2 ] true :: false :: true :: nil = [ true , false , true ] op::( false , op::( true , nil ) ) = false :: [ true ] = [ false , true ]

  6. 5.3 Length, Append, Reverse, Concat und Tabulate Länge einer Liste (SML: length) : length : ‘a list → int fun length nil = 0 | length (x::xr) = 1 + length xr Beispiel : length [1,2,3] = 3 Regeln durch Schlüsselwort „|“ getrennt. Das Muster (Pattern) (x::xr) führt zwei Variablen x und xr ein, die im Rumpf der Regel benutzt werden können. Prozeduren mit mehreren Regeln bezeichnet man als regelbasiert. Im Rumpf nicht benutzte Variablen können im Muster der Regel durch das Wildcard-Symbol _ ersetzt werden. Konkatenation zweier Listen (SML: op@) : append : ‘a list * ‘a list → ‘a list fun append (nil,ys) = ys | append (x::xr,ys) = x :: append(xr,ys) Beispiel : append ( [3] , [1,4] ) = [3,1,4]

  7. 5.3 Length, Append, Reverse, Concat und Tabulate Reversierung einer Liste (SML: rev) : reverse : ‘a list → ‘a list fun reverse nil = nil | reverse (x::xr) = reverse xr @ [x] Beispiel : reverse [1,2,3] = [3,2,1] Konkatenation von Elementlisten (SML: List.concat) : concat : ‘a list list → ‘a list fun concat nil = nil | concat (x::xr) = x @ concat xr Beispiel : concat [ [3] , [1,2] , [ ] ] = [3,1,2] Tabulate (SML: List.tabulate) : tabulate : int * ( int → ‘a ) → ‘a list fun tabulate (n,f) = if n<1 then nil else tabulate(n-1,f) @ [f(n-1)] Beispiel : tabulate(5,(fn x => x*x)) = [0,1,4,9,16] tabulate (n,f) = [f(0),...,f(n-1)]

  8. 5.4 Map, Filter, Exists und All Map (SML: map) : map : (‘a → ‘b) → ‘a list → ‘b list fun map f nil = nil | map f (x::xr) = (f x)::(map f xr) Beispiel : map op~ [2,4,3] = [~2,~4,~3] Ambige Deklaration : val maplen = map length (Warning! Value polymorphism ...) Problem behebbar durch einen nicht expansiven Ausdruck. Man verwende eine Abstraktion : val maplen = fn xs => map length xs Filter (SML: List.filter) : filter : (‘a → bool) → ‘a list→ ‘a list fun filter f nil = nil | filter f (x::xr) = if f x then x :: filter f xr else filter f xr Beispiel : filter (fn x => x>2) [0,1,2,4,7] = [4,7] Filter liefert alle Elemente einer Liste, für die die Prozedur f den Wert true liefert.

  9. 5.4 Map, Filter, Exists und All e1 orelse e2 = if e1 then true else e2 e1 andalso e2 = if e1 then e2 else false Exists (SML: List.exists) : exists : (‘a → bool) → ‘a list → bool fun exists f nil = false | exists f (x::xr) = f x orelse exists f xr Beispiel : exists (fn x => x>2) [0,1,2,4,7] = true Exists testet, ob mind. ein Element der Liste true liefert für die Prozedur f. All (SML: List.all) : all : (‘a → bool) → ‘a list→ bool fun all f nil = true | all f (x::xr) = f x andalso all f xr Beispiel : all (fn x => x>2) [0,1,2,4,7] = false All testet, ob jedes Element der Liste true liefert für die Prozedur f.

  10. 5.5 Faltungsprozeduren fun foldl f s nil = s | foldl f s (x::xr) = foldl f (f(x,s)) xr fun foldr f s nil = s | foldr f s (x::xr) = f(x,foldr f s xr) Typ : (‘a * ‘b → ‘b) → ‘b → ‘a list → ‘b Funktionsweise : foldr f s [x1,...,xn] = f(x1,...f(xn-1,f(xn,s))...) foldl f s [x1,...,xn] = f(xn,...f(x2,f(x1,s))...) f f x1 f x3 f x2 f x2 f x3 s x1 s foldr f s [x1,x2,x3] foldl f s [x1,x2,x3]

  11. 5.5 Faltungsprozeduren fun foldr f s xs = foldl f s rev(xs) Vereinfachte Deklarationen einiger Listenprozeduren : fun length xs = foldl (fn (x,n) => n+1) 0 xs fun append (xs,ys) = foldr op:: ys xs fun rev xs = foldl op:: nil xs fun map f = foldr (fn (x,yr) => (f x)::yr) nil fun concat xs = foldr op@ nil xs fun exists f = foldl (fn (x,b) => b orelse f x) false fun all f = foldl (fn (x,b) => b andalso f x) true

  12. 5.6 hd, tl, null und Ausnahmen hd : ‘a list → ‘a fun hd nil = raise Empty | hd (x::xr) = x fun tl nil = raise Empty | tl (x::xr) = xr tl : ‘a list → ‘a list null : ‘a list → bool fun null nil = true | null (x::xr) = false hd liefert den Kopf (head), tl liefert den Rumpf (tail) einer Liste. Auf eine leere Liste angewendet, werfen sie die Ausnahme Empty. (exception) Wenn bei der Ausführung eines Programms eine Ausnahme geworfen wird, bricht der Interpreter die Ausführung des Programms ab und liefert eine entsprechende Fehlermeldung. null testet, ob eine Liste leer ist. Oft kann man die Beschränkung auf einen Typ mit Gleichheit umgehen, indem man in der Prozedur null xs an Stelle von xs=nil verwendet. Typen mit Gleichheit werden z.B. mit ‘‘a (lies alpha 2-strich) bezeichnet, im Gegensatz zum allgemeinen Typ ‘a (lies alpha).

  13. 5.7 Regelbasierte Prozeduren Regel: <Prozedurbezeichner><Muster>...<Muster> = <Rumpf> Muster: Konstanten, Bezeichner, _ , (M1 : t), (M1::M2), (M1,...,Mn) und [M1,...,Mn] mit M1,...,Mn Muster und t Typ Ein Bezeichner darf höchstens einmal in einem Muster (pattern) auftreten und wird als Variable der Regel bezeichnet. Ein Wert v trifft ein Muster M (pattern matching), wenn ... • M ist ein Bezeichner oder das Wildcard-Symbol 2. M ist eine Konstante und v ist der Wert, den die Konstante beschreibt 3. M hat die Form (M‘ : t) und v trifft M‘ (der Typ spielt also keine Rolle!) 4. M hat die Form (M1 :: M2) und v ist eine Liste, deren Kopf M1 und deren Rumpf M2 trifft. 5. M hat die Form [M1,...,Mn] und v ist eine n-elementig Liste [v1,...,vn], deren Elemente vi die entsprechenden Muster Mi treffen. 6. M hat die Form (M1,...,Mn) und v ist ein n-stelliges Tupel <v1,...,vn>, dessen Komponenten vi die entsprechenden Muster Mi treffen.

  14. 5.7 Regelbasierte Prozeduren Die Regeln einer Prozedur heißen disjunkt, wenn ihre Muster disjunkt sind, also wenn kein Wert mehr als eines der Muster trifft. Die Regeln einer Prozedur heißen erschöpfend, wenn ihre Muster den Argumenttyp der Prozedur erschöpfen, also wenn jeder Wert des Argumenttyps mindestens eines der Muster trifft. Falls die Regeln disjunkt sind spielt die Reihenfolge keine Rolle, andernfalls ist die Reihenfolge sehr wichtig, da eineRegel nur dann anwendbar ist, wenn die vor ihr stehenden Regeln nicht anwendbar sind. Unerwünschte Argumente sollte man mithilfe einer zusätzlichen Ausnahmeregel behandeln.

  15. 5.8 Sortieren von ganzzahligen Listen Eine Liste [x1,...,xn]  ℒ (ℤ) heißt sortiert, wenn x1 ≤ ... ≤ xn gilt. fun sorted (x::y::zs) = x<=y andalso sorted(y::zs) | sorted _ = true Zwei Listen heißen bis auf Permutation gleich, wenn sie bis auf die Reihenfolge ihrer Elemente gleich sind. ∀ xs,ys  ℒ (ℤ) : xs und ys bis auf Permutation gleich ⇔ sort(xs) = sort(ys) Es existiert genau eine Sortierfunktion sort  ℒ (ℤ) → ℒ (ℤ). Sortieren durch Einfügen : Schema: sort(x::xr) = insert(x,sort(xr)) fun insert (x,nil) = [x] | insert (x,y::yr) = if x<=y then x::y::yr else y::insert(x,yr) val isort = foldl insert nil insert fügt das Element x in eine sortierte Liste xs ein, so dass die so entstehende List immer noch sortiert ist. isort realisiert Sortieren durch Einfügen.

  16. 5.8 Sortieren von ganzzahligen Listen Sortieren durch Mischen : Schema: sort(xs@ys) = merge(sort(xs),sort(ys)) fun merge (nil,xs) = ys | merge (xs,nil) = xs | merge (x::xr,y::yr) = if x<=y then x::merge(xr,y:yr) else y::merge(x::xr,yr) fun split xs = foldl (fn (x,(ys,zs)) => (zs,x::ys)) (nil,nil) xs fun msort [ ] = [ ] | msort [x] = [x] | msort xs = let val (ys,zs) = split xs in merge(msort ys, msort zs) end merge verschmilzt zwei sortierte Listen zu einer sortierten Liste. split zerlegt eine Liste in zwei etwa gleichgrosse Teillisten. msort realisiert Sortieren durch Mischen.

  17. 5.9 Polymorphe Sortierprozeduren Die Sortierung ist immer abhängig von der gewählten Ordnung. Um Sortieren durch Einfügen polymorph zu schreiben, müssen wir ein zusätzliches Argument einbinden, welches als Prozedur f die gewählte Ordnung entscheidet. fun pisort order = let fun insert (x,nil) = [x] | insert (x,y::yr) = if order(x,y) then x::y::yr else y::insert(x,yr) in foldl insert nil end Typ : pisort : (‘a * ‘a → bool) → ‘a list → ‘a list vordeklarierte polymorphe Sortierprozedur : Listsort.sort vordeklarierte Ordnungen : Int.compare , Real.compare

More Related