Listen Richard Göbel
Beispiel Studenten einer Vorlesung Datentyp Array public class Vorlesung { String bezeichnung; Dozent dozent; int sws; int ects; Student[] teilnehmer; int anzTeilnehmer; } Ansatz Array Wahl der Größe des Array? Vergrößerung des Array?
Darstellung - Anfangsgröße Maximale Größe oder typische Größe wählen? Studenten für jede Vorlesung speichern: Typische Größe: 40? Maximale Größe: 50, 100, 200?
Speicherplatzverbrauch – Beispiel Teilnehmer
Erzeugen eines Arrays mit einer typische Größe Alternativer Ansatz Erzeugen eines Arrays mit einer typische Größe Vergrößern der Kapazität des Arrays: Erzeugung eines neuen Arrays Kopieren der vorhandenen Elemente in das neue Array Ersetzen des alten durch das neue Array Wie sollte die Größe eines Array wachsen? um ein Element? um eine konstante Zahl (z.B. 10)? um einen konstanten Faktor (also exponentiell)? Standardlösung: ArrayList
ArrayList- Übersicht Datentyp Konstruktoren Kapazität Vergrößern Objekt einfügen Objekt lesen Objekt ersetzen Beispiele
ArrayList - Attribute public class ArrayList<E> { private E[] elementData; private int size; public int size() return size; } . . .
ArrayList - Konstruktoren public ArrayList(int initialCapacity) { if (initialCapacity < 0) throw new IllegalArgumentException( "Illegal Capacity: “ + initialCapacity); elementData = (E[]) new Object[initialCapacity]; } public ArrayList() this(10);
ArrayList - Kapazität Vergrößern public void ensureCapacity(int minCapacity) { int oldCapacity = elementData.length; if (minCapacity > oldCapacity) Object oldData[] = elementData; int newCapacity = (oldCapacity * 3)/2 + 1; if (newCapacity < minCapacity) newCapacity = minCapacity; elementData = (E[]) new Object[newCapacity]; System.arraycopy( oldData,0,elementData,0, size); }
ArrayList - Objekt einfügen public boolean add(E o) { ensureCapacity(size + 1); elementData[size++] = o; return true; }
ArrayList - Objekt lesen public E get(int index) { if (index<0 || index>=size) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); return elementData[index]; }
ArrayList - Objekt ersetzen public E add(int index, E element) { if (index<0 || index>=size) throw new IndexOutOfBoundsException( "Index: "+index+", Size: "+size); E oldValue = elementData[index]; elementData[index] = element; return oldValue; }
ArrayList – Beispiel I ArrayList<String> l = new ArrayList<String>(); for (int i = 0; i < 100; i++) { l.add("Element " + i); System.out.println(i + ": " + l.get(i)); System.out.println("size: " + l.size()); System.out.println( "capacity: " + l.toArray().length); }
ArrayList – Beispiel II l.add(150, "Element 150"); System.out.println("150: " + l.get(150)); System.out.println("size: " + l.size()); System.out.println( "capacity: " + l.toArray().length); l.add(1000, "Element 1000"); System.out.println("1000: " + l.get(150));
ArrayList - Diskussion Niedriger durchschnittlicher Zeitaufwand für das Einfügen O(1), (schlechtester Fall: O(n)) und den wahlfreien Zugriff O(1) Geringer zusätzlicher Verbrauch an Speicherplatz Hoher Kopieraufwand speziell bei dem Vergrößern großer Listen
Motivation: Verkettete Listen vermeiden Kopieraufwand beim Einfügen LinkedList - Konzept Motivation: Verkettete Listen vermeiden Kopieraufwand beim Einfügen Für jedes Objekt der Liste existiert ein Listenobjekt mit drei Referenzen Jeweils eine Referenz verweist auf Vorgänger und Nachfolger in der Liste Eine Referenz verweist auf das enthaltene Element
Verkettete Liste - Attribute und Konstruktor public class LinkedList<E> { private Entry<E> header = new Entry<E>(null, null, null); private int size = 0; public LinkedList() header.next = header.previous = header; } public int size() return size; . . .
Listenelement - Attribute und Konstruktor private static class Entry<E> { E element; Entry<E> next; Entry<E> previous; Entry(E element, Entry<E> next, Entry<E> previous) this.element = element; this.next = next; this.previous = previous; }
LinkedList - Attribut eines Listenelements String element; Entry<String> next; Entry<String> previous; ”abc” ”def” ”ghi”
Klasse LinkedList - Methode add public boolean add(E o) { addBefore(o, header); return true; } private Entry<E> addBefore(E o, Entry<E> e) Entry<E> newEntry = new Entry<E>(o, e, e.previous); newEntry.previous.next = newEntry; newEntry.next.previous = newEntry; size++; return newEntry;
Klasse LinkedList - Methode get public E get(int index) { return entry(index).element; } private Entry<E> entry(int index) if (index < 0 || index >= size) throw new IndexOutOfBoundsException(…); Entry<E> e = header; if (index < (size >> 1)) for (int i = 0; i <= index; i++) e = e.next; else for (int i = size; i > index; i--) e = e.previous; return e;
Klasse LinkedList - Methode set public E set(int index, E element) { Entry<E> e = entry(index); E oldVal = e.element; e.element = element; return oldVal; }
LinkedList - Beispiel LinkedList<String> l = new LinkedList<String> (); for (int i = 0; i < 5; i++) { l.add("Element " + i); System.out.println(i + ": " + l.get(150)); System.out.println ("size: " + l.size()); } l.set(10, "Element 10");
LinkedList - Diskussion Niedriger Zeitaufwand für das Einfügen O(1) Hoher Aufwand für den wahlfreien Zugriff O(n) Für jedes Element der Liste wird genau ein Objekt der Klasse Entry benötigt.