Kapitel 11 Abstrakte Datentypen © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 1 11.1 Grundlagen Ein Datentyp ist eine strukturierte Menge von Werten. Damit ist gemeint, dass auf den Elementen des Typs eine Anzahl von Operationen (mit bestimmten zugesicherten Eigenschaften) definiert sind, mit deren Hilfe man Objekte (Daten) dieses Typs manipulieren kann. Man kann einen Datentyp in der Regel auf sehr verschiedene Art realisieren. Trotzdem bleibt er aus Sicht der Benutzer derselbe Typ, solange die Implementierungen die Zusicherungen des Typs einhalten. Deshalb muss man zwischen einem abstrakten Datentyp (ADT) und seiner konkreten Realisierung unterscheiden: Externe Sicht und interne Details der Implementierung sollten möglichst strikt getrennt werden (Prinzip des Information Hiding). © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 2 11.1 Grundlagen Abstrakter Datentyp (ADT) ist eine Methode zur Spezifikation (Beschreibung) dessen, was ein Datentyp an Funktionalität leisten soll, ohne dabei schon festzulegen, wie die Funktionalität zu implementieren ist Black-Box Prinzip in Form eines Kontrakts zwischen Benutzer und Implementierer: • Implementierer realisiert die spezifizierte Funktionalität • Benutzer hält sich an die in der Spezifikation dargestellten Benutzungsbedingungen Grundlegendes Konzept: Abstraktion von der konkreten Realisierung durch eine spezifizierte Schnittstelle, ein sog. Interface © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 3 11.1 Grundlagen Interface: Beschreibung der Funktionalität in Form der erlaubten Operationsnamen und ihrer Argumente sowie der mit den Namen verbundenen Bedeutung (Bedeutungsbeschreibung ohne Bezug auf die konkrete Realisierung!) Strenge Trennung durch ein abstraktes Interface ermöglicht • Austausch von Implementierungen ohne Wissen des Benutzers • bessere Wiederverwendung (re-use) von Programmen Spezifikation grundlegend für die Überprüfung der Korrektheit einer Realisierung! ADT-Spezifikation = Signatur + Semantik • Signatur gibt formale Beschreibung der Definitions- und Wertebereiche der Operationen • Semantik: Bedeutung der Operationen © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 4 11.1.1 Signatur Datentyp: WN a: b: op1: WN op2: WN × WN op3: WN × WN Ende Datentyp → → → → → WN WN WN WN WN Signatur von WN: legt die Syntax von WN-Termen exakt fest Sorte (Grundmenge) WN für den Datentyp Operationssymbole a b op1 op2 op3 Zu jedem Operationssymbol wird seine Stelligkeit angegeben: – Argumente und ihre Sorten – Ergebnis der Operation Stelligkeit gibt ersten Anhaltspunkt für Interpretation. Die Namen haben zunächst keine Bedeutung! © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 5 11.1.1 Signatur Menge der WN-Terme gemäß der Datentypbeschreibung für WN ist definiert durch: a ist ein WN-Term und b ist ein WN-Term Sind t1, t2 und t WN-Terme, dann auch (i) op1(t) (ii) op2(t1 , t2 ) (iii) op3(t1 , t2 ) Alle WN-Terme werden durch endlich häufige Anwendung der Regeln (1) und (2) definiert WN ist homogener Datentyp, d.h. die Datentypbeschreibung verwendet nur die Sorte WN selbst Beispiel: a und b sind Namen für Konstanten, auch null-stellige Operationssymbole genannt a op1(a) op2(op1(a), b) sind WN-Terme op1(a, b) op3(b) sind keine WN-Terme, da Stelligkeiten verletzt © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 6 11.1.1 Signatur Heterogener Datentyp verwendet auch andere Sorten Datentyp: L benutzt { J, B, N } e: → L i: L × J → L e?:L → B c: L × L → L l: L → N Ende Datentyp Sorte L für den Datentyp, Sorten J, B, N bereits bekannt Operationssymbole e i e? c l Die Art eines Terms wird durch den Wertebereich festgelegt: e?(e) kein L-Term, sondern ein B-Term l(e) kein L-Term, sondern ein N-Term c(e?(e), e) kein gültiger L-Term © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 7 11.1.1 Signatur Signatur zu einem Datentyp: Gesamtheit der in einer Datentypbeschreibung gegebenen syntaktischen Information Definition: mehrsortige Signatur Sei SO eine Menge von Sorten, OP eine Menge von Operationssymbolen. Das Tripel SIG = (SO, OP, ar) mit ar: OP → SO* × SO (Aritätsfunktion oder Stelligkeits-funktion) ar ordnet jedem Operationssymbol seine Stelligkeit zu Ist ar(op) = (S1 S2 … Sn , S) für ein op ∈ OP, so heissen S1 S2 … Sn die Argumentsorten von op und S die Ergebnissorte von op Ein null-stelliges Operationssymbol op hat die Stelligkeit ar(op) = (ε, S) und wird auch als Konstantensymbol bezeichnet © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 8 11.1.1 Signatur Beispiel: Datentyp: WN a: b: op1: WN op2: WN × WN op3: WN × WN Ende Datentyp → → → → → WN WN WN WN WN SIGWN = ( { WN }, { a, b, op1, op2, op3 }, arWN ) mit arWN (a) = arWN (b) = (ε, WN) arWN (op1) = (WN, WN) arWN (op2) = arWN (op3) = (WN WN, WN) © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 9 11.1.1 Signatur Beispiel: Datentyp: L benutzt { J, B, N } e: → L i: L×J → L e?: L → B c: L × L → L l: L → N Ende Datentyp SIGL = ( { L, J, B, N }, { e, i, e?, c, l }, arL ) mit arL (e) = (ε, L) arL (i) = (L J, L) arL (e?) = (L, B) arL (c) = (L L, L) arL (l) = (L, N) © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 10 11.1.2 Semantik Interpretation eines ADT: • Was fehlt: Information über die Bedeutung (Semantik) der Terme, d.h. eine Möglichkeit der Interpretation Mögliche Vorgehensweisen für die Zuordnung von Semantik: Angabe einer passenden Interpretation Beispiel: Angabe möglicher Interpretationen des Datentyps WN durch Aufzählung der zu ( WN, (a, b, op1, op2, op3) ) jeweils über die Position korrespondierenden Grundmengen bzw. Operationen © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 11 11.1.2 Semantik Beispiel (Fort.): Interpretation I1 = ( N 0 , (0, 1, succ, +, ∗) ) : • 0: → N 0 und 1: → N 0 entsprechen den konstanten Funktionen, die als Ergebnis 0 bzw. 1 liefern • succ: N 0 → N 0 ist Nachfolgerfunktion (successor) mit succ(n) = n + 1 • Stelligkeit der Operationen paßt jeweils zu der der Operationssymbole! Mögliche andere Interpretationen bei gleicher Grundmenge N 0 : I2 = ( N 0 , (1, 0, succ, +, ∗) ) I3 = ( N 0 , (0, 1, succ, ∗, +) ) I4 = ( N 0 , (1, 0, succ, ∗, +) ) Interpretation von op1 als + oder ∗ nicht möglich wegen unterschiedlicher Stelligkeiten! © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 12 11.1.2 Semantik Beispiel (Fort.): Andere mögliche Interpretationen des Datentyps WN, basierend auf der Grundmenge B = { #t , #f } mit den Funktionen ¬, ∧, ∨: I5 = ( B , I6 = ( B , I7 = ( B , I8 = ( B , (#t, #f, ¬, ∧, ∨) ) (#f, #t, ¬, ∧, ∨) ) (#t, #f, ¬, ∨, ∧) ) (#f, #t, ¬, ∨, ∧) ) I5 Æ Darstellung des Datentyps WN mit besser verständlichen Namen: Datentyp: BOOL true: false: not: BOOL and: BOOL × BOOL or: BOOL × BOOL © Xiaoyi Jiang → → → → → BOOL BOOL BOOL BOOL BOOL Signatur von BOOL Informatik II – Datenstrukturen und Algorithmen 13 11.1.2 Semantik Beispiel (Fort.): Weitere Interpretationen basierend auf anderen Grundmengen: I9 = ( { 0, 1 }, (0, 1, id, ⊕, ⊗) ) wobei id: { 0, 1 } → { 0, 1 } mit id(0) = 0, id(1) = 1 ⊕: { 0, 1 } × { 0, 1 } → { 0, 1 } mit ⊕(0, 0) = ⊕(1, 1) = 0, ⊕(0, 1) = ⊕(1, 0) = 1 ⊗: { 0, 1 } × { 0, 1 } → { 0, 1 } mit ⊗(0, 0) = ⊗(0, 1) = 0, ⊗(1, 0) = ⊗(1, 1) = 1 I10 = ( { ♥ }, (♥, ♥, id, ♦, ♦) ) wobei id: { ♥ } → { ♥ } mit id(♥) = ♥ ♦ : { ♥ } × { ♥ } → { ♥ } mit ♦(♥, ♥) = ♥ © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 14 11.1.2 Semantik Jede passende Interpretation eines Datentyps ist ein konkretes Modell für die abstrakte Beschreibung, die den beschriebenen Anforderungen genügt I1 Datentyp NN … Signatur … Ende Datentyp Modell 1 I2 Modell 2 I3 … In Modell 3 … Modell n Bestandteile eines Modells: Grundmengen mit den entsprechenden Operationen über den Grundmengen © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 15 11.1.2 Semantik Signatur SIG = (SO, OP, ar): • beschreibt Syntax der definierten Terme mit Sorten und Operationssymbole • Signatur schränkt durch die Syntax die Menge der möglichen Interpretationen ein. Interpretation: gibt zu jeder Sorte eine Grundmenge - die sogenannte Trägermenge - und zu jedem Operationssymbol eine gemäß der Stelligkeit passende Operation an Ergänzung der Semantikbeschreibung eines Modells durch Gleichungen zwischen Termen über der Signatur © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 16 11.1.2 Semantik Beispiel: Spezifikation eines Datentyps aus Signatur und Gleichungen Datentyp: BOOL true: false: not: BOOL and: BOOL × BOOL or: BOOL × BOOL → → → → → BOOL BOOL BOOL BOOL BOOL Signatur von BOOL Gleichungen mit Variablen X, Y ∈ BOOL not(true) = false (B1) not(not(X)) = X (B2) and(false, X) = false (B3) and(true, X) = X (B4) or(X, Y) = not(and(not(X), not(Y))) (B5) Ende Datentyp © Xiaoyi Jiang Semantik von BOOL Informatik II – Datenstrukturen und Algorithmen 17 11.1.2 Semantik Beispiel: ADT NAT zur Beschreibung der Menge N Datentyp: NAT null: succ: NAT add: NAT × NAT mult: NAT × NAT → → → → NAT NAT NAT NAT Gleichungen mit Variablen X, Y ∈ NAT add(X, null) = X add(X, succ(Y)) = succ(add(X, Y)) add(X, Y) = add(Y, X) mult(X, null) = null mult(X, succ(Y)) = add(X, mult(X, Y)) mult(X, Y) = mult(Y, X) Ende Datentyp © Xiaoyi Jiang 0 Informatik II – Datenstrukturen und Algorithmen (N1) (N2) (N3) (N4) (N5) (N6) 18 11.1.2 Semantik null und succ reichen zur Darstellung jedes Elementes aus NAT aus: succ(succ(…succ(null)…)) k-mal k-mal Ist eine Operation für die Argumente null und succ für alle Fälle beschrieben, so ist ihr Verhalten vollständig beschrieben. mult wird schrittweise auf add zurückgeführt, add schrittweise auf succ Æ mult und add beschreiben Hilfsoperationen, deren Ergebnisse auch immer allein mit null und succ dargestellt werden können (N 0, (0, succ, +, ∗)) mit succ(n) = n + 1 ist eine eine mögliche Interpretation von (NAT, (null, succ, add, mult)), der Zahl k ∈ N entspricht der NAT-Term succ(succ(…succ(null)…)) k-mal k-mal © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 0 19 11.1.2 Semantik Beweis weiterer Eigenschaften eines Modells: mult(succ(null), t) = t , denn: mult(succ(null), t) =(N6) mult(t, succ(null)) =(N5) add(t, mult(t, null)) =(N4) add(t, null) =(N1) t © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 20 11.1.3 Erweiterte ADTs mit Parametern ADT für Paare in Scheme: Datentyp: PAIR parm ELEM benutzt { } cons: ELEM × ELEM → PAIR car: PAIR → ELEM cdr: PAIR → ELEM Gleichungen mit Variablen E1, E2 ∈ ELEM (P1) car(cons(E1, E2 )) = E1 (P2) cdr(cons(E1, E2 )) = E2 Ende Datentyp ELEM steht für den Typ der im PAIR zu speichernden Objekte Beschreibung ohne nullstellige Operationssymbole (Konstanten) Æ Terme der Sorte PAIR können nur durch die Parametrisierung über ELEM entstehen Ersetzen von ELEM durch einen aktuellen Parameter: PAIR-BOOL := PAIR mit ELEM = BOOL © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 21 11.1.3 Erweiterte ADTs mit Parametern ADT für Listen in Scheme: Datentyp: LIST parm ELEM benutzt { BOOL, NAT } '(): → LIST cons: ELEM × LIST → LIST append: LIST × LIST → LIST null?: LIST → BOOL length: LIST → NAT → ELEM car: LIST cdr: LIST → LIST Gleichungen mit Variablen E ∈ ELEM, L, L1, L2 ∈ LIST null?('()) = true (L1) null?(cons(E, L)) = false length('()) = null (L3) length(cons(E, L)) = succ(length(L)) car('()) = errorELEM (L5) car(cons(E, L)) = E cdr('()) = errorLIST (L7) cdr(cons(E, L)) = L append('(), L) = L append(cons(E, L1 ), L2 ) = cons(E, append(L1, L2 )) append(L, '()) = L Ende Datentyp © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen (L2) (L4) (L6) (L8) (L9) (L10) (L11) 22 11.1.3 Erweiterte ADTs mit Parametern Konstruktionsprinzip: Jede Liste ist ein aus einem Element und einer weiteren Liste bestehendes Paar, null-stelliges Operationssymbol '() entspricht der leeren Liste Konstruktoren '() und cons reichen aus, um alle korrekten Listen zu erzeugen Beobachter null? und length zur Unterscheidung von Listen Konstante Fehlerelemente errorELEM und errorLIST stehen als Repräsentanten für Fehlermeldungen des SCHEME-Interpreters. Aus jedem LIST-Term können cdr durch (L8) und append durch (L9 - L11) eliminiert werden © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 23 11.1.4 Implementierung Abstrakte Datentypen in Java: In Java kann man einen ADT durch ein Interface definieren. Das gilt allerdings nur mit Einschränkungen: Man kann in einem Interface nicht angeben, wie ein Objekt des Typs erzeugt wird (Konstruktoren sind nicht erlaubt), und man kann die Semantik der Zugriffsfunktionen nur informell (als Kommentare) angeben. Jede Java–Klasse definiert durch ihre public–Methoden einen ADT, den sie gleichzeitig implementiert. In Java sind die Begriffe abstrakter und konkreter Datentyp nicht streng getrennt. Aus diesem Grund ist es manchmal sinnvoll, aus einer Java–Klasse den durch sie definierten ADT abzuleiten. (Leider gibt es in Java dafür kein sprachliches Ausdrucksmittel.) © Xiaoyi Jiang Informatik II – Datenstrukturen und Algorithmen 24