Ordnung im Materiallager: Datenstrukturen Programme und Datenverwaltung Datenverwaltung durch Arrays Eigenschaften von Arrays Implementierung mit Arrays Sortieren Suchen im sortierten Array
Was ist ein Programm? Ein Objekt, das eine Aufgabe löst. (Klasse mit main-methode) beansprucht dabei die Hilfe anderer Objekte. Die anderen Objekte bieten Operationen (sag mir mal, wie spät es in New York ist, formatiere bitte folgenden Text, lies alle ankommenden Ziffern ein) und Datenhaltung (merk dir mal folgende Zahl, buche 100 vom Konto ab, sag mir den Vornamen des Kunden) (c)schmiedecke 04 Pr10-Datenstrukturen 2
Objekte als Datenbehälter Jedes Objekt ist ein Datenbehälter (Zustand) Programm verwaltet oft viele Objekte eines Typs, schafft sich dazu einen Aggregat-Typ (Sammeltyp) class Fuhrpark { Auto auto1 = new Auto(), auto2 = new Auto(), auto3 = new Auto(), auto4 = new Auto(), auto5 = new Auto(), auto6 = new Auto(); LKW lkw1 = new LKW(), lkw2 = new LKW(), lkw3 = new LKW(); Krad krad1 = new Krad(); (c)schmiedecke 04 Pr10-Datenstrukturen 3
Verallgemeinerte Datenbehälter spezieller Aggregattyp ist sehr eingeschränkt Besser: ein Typ, der eine variable Anzahl von Objekten speichern kann Standardoperationen: - hinzufügen - suchen /lesen/ansehen - entnehmen / löschen - aktuelleanzahl - evtl. maximaleanzahl welchen Typ sollen die zu speichernden Elemente haben? - Objekt, Auto, LKW, Krad? - oft eine spezifische Oberklasse: Fahrzeug (c)schmiedecke 04 Pr10-Datenstrukturen 4
Datenbehälter-Interface interface Fuhrpark { public void int hinzufügen(fahrzeug fz); public int suchen(welcher suchen(); Parameter?); public Fahrzeug lesen(welcher lesen(); Parameter?); public void loeschen(welcher loeschen(); Parameter?); public int anzahl(); Elementtyp Fahrzeug Auto Fahrzeug LKW Krad (c)schmiedecke 04 Pr10-Datenstrukturen 5
Präzisierungs-Fragen wie sollen die Elemente abgelegt werden? geordnet / ungeordnet mit / ohne Mehrfacheinträge(n) mit / ohne Löschmöglichkeit mit / ohne Anzahlbegrenzung wie sollen die Elemente auffindbar sein? per Index per Schlüssel durch Suchen (c)schmiedecke 04 Pr10-Datenstrukturen 6
Indizierter Datenbehälter Modell Parkhaus: nummerierte Plätze interface FuhrparkIndex { // indiziert public int hinzufuegen(fahrzeug fz); // und wo abgestellt? public int suchen(fahrzeug fz); // wo steht...? public Fahrzeug lesen(int index); // welches steht dort? public void loeschen(int index); public int anzahl(); // wegfahren, Platz frei // wieviele Fahrzeuge? (c)schmiedecke 04 Pr10-Datenstrukturen 7
Datenhaltung durch Arrays: Direkte Unterstützung der indizierten Datenhaltung In praktisch allen Programmiersprachen Entspricht der natürlichen Nutzung des Speichers 40147B 40147C 40147D 40147E 40147F 401480 401481 Ein Array (Feld, Reihung) ist eine indizierte Folge mit fester Länge von Elementen desselben Typs. (c)schmiedecke 04 Pr10-Datenstrukturen 8
Statt: class Fuhrpark { Auto auto1 = new Auto(), auto2 = new Auto(), auto3 = new Auto(), auto4 = new Auto(), auto5 = new Auto(), auto6 = new Auto(); LKW lkw1 = new LKW(), lkw2 = new LKW(), lkw3 = new LKW(); Krad krad1 = new Krad(); Jedes Auto hat seinen eigenen Namen, Ähnlichkeiten sind zufällig (c)schmiedecke 04 Pr10-Datenstrukturen 9
...schreiben wir jetzt: class Fuhrpark { Auto[] auto = new Auto[6]; LKW[] lkw = new LKW[5]; Krad[] krad = new Krad[3]; nur Garagen, nix drin! // Füllen der Elemente, z.b.im Konstruktor public Fuhrpark() { auto[0] = new Auto(); lkw[0] = new LKW(); auto[1] = new Auto(); lkw[1] = new LKW(); auto[2] = new Auto(); lkw[2] = new LKW(); auto[3] = new Auto(); auto[4] = new Auto(); krad[0] = new Krad(); auto[5] = new Auto(); // Die Plätze lkw[3], lkw[4] und krad[1], krad[2] // bleiben heute leer (null) einparken bitte! (c)schmiedecke 04 Pr10-Datenstrukturen 10
Wissenswertes über Arrays: Der Elementtyp kann auch ein primitiver Typ sein: int[] personalnummer = new int[1000]; Arrays sind Objekttypen (unabhängig vom Elementtyp): Object datenbehälter = new int[10000]; Die Indizierung beginnt bei 0 (natürlich...) personalnummer[0] bis personalnummer[999] Die Länge des Arrays steht im Feld length: personalnummer.length // nur Lesezugriff! Daraus ergibt sich folgende Standard-for-Schleife: for (int index=0; index<array.length; index++) operationauf(array[index]); (c)schmiedecke 04 Pr10-Datenstrukturen 11
Iterieren über ein Array Standardschleife: for (int index=0; index<array.length; index++) operationon(array[index]); Vereinfachte Schleife: for (Element element : array) operationon(element); // index in der Operation nicht verfügbar (c)schmiedecke 06 inf1-8a-arrays and Collections 12
... noch einmal Fuhrpark: class Fuhrpark { Auto[] auto = new Auto[6]; LKW[] lkw = new LKW[5]; Krad[] krad = new Krad[3]; // Füllen der Elemente im Konstruktor public Fuhrpark() { for (int i=0;i<auto.lenth;i++) auto[i] = new Auto(); for (int i=0; i<3; i++) lkw[i] = new LKW(); krad[0] = new Krad(); Einpark- Schleife // lkw[3], lkw[4] und krad[1], krad[2] // behalten den Wert null (c)schmiedecke 04 Pr10-Datenstrukturen 13
Etch-A-Sketch Was wird gezeichnet? (c)schmiedecke 04 Pr10-Datenstrukturen 14
Wissenswertes über Arrays II: Die Initialisierung der Elemente kann durch einen Initialisierer erfolgen: int[] zulassung = {1988, 1992, 1999; String[] = {"fachberater", name, abt.tostring(); (c)schmiedecke 04 Pr10-Datenstrukturen 15
Wissenswertes über Arrays III: Mehrdimensionale Arrays:"Array of Arrays" int matrix[][] = new int[4][3]; Längenfestlegung nur für die erste Dimension zwingend, Instanziierung der weitern Dim. separat Mehrdimensionale Arrays müssen nicht rechteckig sein: int dreieck[][] = new int[10][]; for (int i=0; i<dreieck.length; i++) { dreieck[i] = new int[i+1]; for (int j=0; j<i+1; j++) dreieck[i][j] = i+j; (c)schmiedecke 04 Pr10-Datenstrukturen 16
Wissenswertes über Arrays VI: Es dürfen nur gültige Indizes verwendet werden. Zugriff mit unzulässigem Index Ausnahme IndexOutOfBoundsException Das Programm wird mit einer Fehlermeldung und einer Diagnose (StackTrace) beendet. Man kann die Ausnahme abfangen und das Programm fortsetzen: try { auto[i] = new Auto(); catch (IndexOutOfBoundsException e) { System.err.println ("es gibt nur 6 Garagen!"); (c)schmiedecke 04 Pr10-Datenstrukturen 17
Was ist eine Ausnahme? Exception-Konzept grundlegend in der OO-Programmierung Foliensatz Exceptions (c)schmiedecke 04 Pr10-Datenstrukturen 18
Indizierter Datenbehälter Modell: Parkhaus, nummerierte Plätze interface FuhrparkIndex { // indiziert public int hinzufuegen(fahrzeug fz); // liefert Index public int suchen(fahrzeug fz); // Vergleichsobjekt public Fahrzeug lesen(int index); public void loeschen(int index); public int anzahl(); (c)schmiedecke 04 Pr10-Datenstrukturen 19
Implementierung mit einem Array class FuhrparkArray implements FuhrparkIndex { // private Attribute private Fahrzeug[] fahrz; private int anzahl = 0; // Standardkonstruktor, feste Groesse public FuhrparkArray() { fahrz = new Fahrzeug[50]; // Konstruktor mit Groessenangabe public FuhrparkArray(int groesse) { fahrz = new Fahrzeug[groesse]; (c)schmiedecke 04 Pr10-Datenstrukturen 20
// Hinzufügen, sofern Platz ist public int hinzufuegen(fahrzeug fz) { if (anzahl>=fahrz.length) return -999; fahrz[anzahl] = fz; anzahl++; return anzahl-1; public int anzahl() { return anzahl; // anzahl // lesen, falls vorhanden public Fahrzeug lesen(int index) { if (index < 0 index >= anzahl) return null; return fahrz[index]; (c)schmiedecke 04 Pr10-Datenstrukturen 21
public int suchen(fahrzeug fz) { if (fz = null) return -999; for (int i=0; i<anzahl; i++) if (fz[i].equals(fz)) return i; // gefunden return -1; // nicht gefunden // löschen und zusammenschieben public void loeschen(int index) { if (index < 0 index >= anzahl) return; for (int i=index; i<anzahl-1; i++) fahrz[i] = fahrz[i+1]; // verschieben fahrz[anzahl-1] = null; anzahl --; // Fertig, Klassenende (c)schmiedecke 04 Pr10-Datenstrukturen 22
Verallgemeinerte Datenbehälter Typ, der eine variable Anzahl von Objekten eines geeigneten Elementtyps speichern kann Standardoperationen: - hinzufügen - suchen /lesen - entnehmen / löschen - aktuelleanzahl - evtl. maximaleanzahl Array ist eine mögliche Implementierungstechnik Vorteil von Arrays: Direktzugriff per Index Nachteil: Feste Länge, mittiges Einfügen/Löschen sehr aufwändig (c)schmiedecke 04 Pr10-Datenstrukturen 23
Stack und Queue (Stapel und Warteschlange) Zwei sehr wichtige Datenbehälter-Typen Identische Schnittstelle, unterschiedliches Verhalten interface Container { void add(object o); Object remove(); interface LiFo extends Container { interface FiFo extends Container { (c)schmiedecke 04 Pr10-Datenstrukturen 24
Array als LiFo class StackArray implements LiFo { private Object[] stack = new Object[size]; private int top = 0; public void add(object o) { if (top == size) return; stack[top] = o; top++; public Object remove() { if (top==0) return null; top --; return stack[top]; (c)schmiedecke 04 Pr10-Datenstrukturen 25
Array als FiFo class QueueArray implements FiFo { private Object[] queue = new Object[size]; private int next=0, count=0; last=0; void add(object obj) { if (count>=size) return; //?! queue[next] = obj; next = (next+1)%size; // modulo count ++; Object remove() { if (count==0) return null; Object o = queue[last]; next count --; last = (last+1)%size; // pos. return o; last 11 12 10 9 (c)schmiedecke 04 Pr10-Datenstrukturen 26 8 7 0 6 1 2 3 4 5
Sortieren im Array Die Klasse FuhrparkArray wird um die Methode sortieren() erweitert. Voraussetzung: Fahrzeug muss eine Methode groesser() enthalten. Hinweis: nach dem Sortieren sind alle bis dahin gelieferten Indizes ungültig! (c)schmiedecke 04 Pr10-Datenstrukturen 27
Sortieren public int sortieren() { // bubblesort // Idee: "schwere" Elemente sinken nach unten for (int i=anzahl-1; i>0; i--) { // rueckwärts Fahrzeug fzi = fahrz[i]; for (int k=i-1; k>=0; k--) { Fahrzeug fzk = fahrz[k]; // vorgänger if (fzk.groesser(fzi)) { //vertauschen: fahrz[i] = fzk; fahrz[k] = fzi; fzi = fzk; // neuer Vergleichswert // for (k // for (i // sortieren Umformulieren: leichte Elemente steigen auf... (c)schmiedecke 04 Pr10-Datenstrukturen 28
Suchen im sortierten Array Der effizienteste Suchalgorithmus ist die Binäre Suche (BinSearch) Sie funktioniert nur im dichten Array (keine Lücken) Die Idee ist einfach: es wird jeweils ermittelt, in welcher Hälfte des Arrays der gesuchte Wert liegen muss. (c)schmiedecke 04 Pr10-Datenstrukturen 29
Binäre Suche public int suchen(fahrzeug fz) { int min = 0, max = anzahl - 1; while (min <= max) { int mitte = (min + max) / 2; Fahrzeug fzm = fahrz[mitte]; if (fzm.groeser(fz)) { max = mitte 1; // oben suchen else if (fz.equals(fzm)) return mitte; else min = mitte + 1; // unten suchen // while return 1; // nicht gefunden // suchen (c)schmiedecke 04 Pr10-Datenstrukturen 30
Sortiertes Einfügen Wir benutzen die suchen-methode. Sie wird wie folgt ergänzt: jeweils vor dem return wird eingefügt: einfuegepunkt = mitte; Die Klasse erhält ein zusätliches privates int- Feld: int einfuegepunkt; An dieser Stelle wird dann der neue Wert eingefügt (c)schmiedecke 04 Pr10-Datenstrukturen 31
Sortiertes Einfügen public void hinzufuegen(fahrzeug fz){ if (suchen(fz) >= 0) // ist schon drin return; if (anzahl >= fahrz.length) throw new VollException(anzahl); // alle fz ab einfuegepunkt verschieben for (int i=anzahl; i>einfuegepunkt; i--) fahrz[i] = fahrz[i-1]; // einfügen am einfuegepunkt fahrz[einfuegepunkt] = fz; anzahl++; // hinzufügen (c)schmiedecke 04 Pr10-Datenstrukturen 32
Genug für heute nächstes Mal gibt es Fertig- Collections