Dein Name PK Aufgabenblatt #7 18.12.2013 Aufgabenblatt #7 Theorie 1: Algorithmen und Datenstrukturen „Was versteht man unter Algorithmen und Datenstrukturen, und wie hängen diese beiden Begriffe zusammen? Unter welchen Bedingungen sind zwei Algorithmen bzw. Datenstrukturen gleich? Wann sind sie es nicht? Nennen Sie fünf unterschiedliche Datenstrukturen und charakterisieren Sie sie.“ Ein Algorithmus ist eine eindeutige Handlungsvorschrift zur Lösung eines Problems. Wohingegen eine Datenstruktur eine Beschreibung ist, wie man Daten relativ zueinander ordnet und wie auf die einzelnen Elementen zugegriffen werden kann. Zusammenhänge: Man kann z.B. einen Algorithmus verwenden, um auf Elemente in einer Datenstruktur zuzugreifen bzw. diese zu durchsuchen. Zwei Algorithmen sind gleich, wenn deren Ergebnis gleich ist. Zwei Datenstrukturen sind gleich, wenn die Art, wie die Daten gespeichert werden und der Suchaufwand gleich ist. Stack: Alle Elemente werden auf einem Stapel gespeichert, man kann nur auf das oberste Element zugreifen bzw. nur oben hinzufügen. Methoden: push, pop, size Array: Alle Elemente werden nebeneinander gespeichert und sind durch Indizes zugreifbar. Alle Elemente müssen denselben Typ haben und die Größe wird spätestens bei der Initialisierung festgelegt. Verkettete Liste: Alle Elemente werden hintereinander gespeichert, wobei ein Element auf das Nächste zeigt und das letzte Element auf null. Daher ist die Anzahl der Elemente nicht begrenzt und das Hinzufügen ist sehr einfach. Das Suchen ist jedoch sehr aufwendig Binärer Baum: Die Elemente werden von oben nach unten hinzugefügt. Das oberste Element wird Wurzel genannt. Alle Elemente kleiner der Wurzel werden im linken Teilzweig eingeordnet und alle Elemente die größer oder gleich dem Knoten sind im rechten Teilzweig. Dieses Schema wird bis zum Ende fortgesetzt. Hashtabelle: Alle Elemente werden an einem bestimmten Index gespeichert. Der Index selbst errechnet sich aus dem Hashcode des Elements. Wenn mehrere Elemente denselben Hashcode haben, werden sie in eine Liste gespeichert. Je mehr Elemente in einer Hashtabelle sind, desto ineffizienter werden die Zugriffe. Theorie 2: Aufwandsabschätzung „Wie kann man den Aufwand eines Algorithmus abschätzen? Wofür stehen O(1), O(log(n)), O(n), O(n·log(n)), O(n2) und O(2n)? Wie wirkt sich eine Verdopplung oder Verhundertfachung von n aus? Wieso kann man konstante Faktoren bei der Aufwandsabschätzung einfach ignorieren?“ Abschätzen von algorithmischen Kosten: Man schätzt nur ab, wie viele Zugriffe zur Ausführung eines Algorithmus nötig sind, sie geben keine genauen Werte an, sondern nur Anhaltspunkte. O(1) = konstante Kosten O(log(n)) = logarithmische Kosten O(n) = lineare Kosten Dein Name PK Aufgabenblatt #7 O(n * log(n)) = super-lineare Kosten O(n²) = quadratische Kosten O(2n) = exponentielle Kosten 18.12.2013 Man kann konstante Faktoren vernachlässigen, da sie meistens recht niedrig sind, und nicht mit n mitwachsen. Daher sind sie zum Vergleichen von Aufwänden nicht relevant. Verdopplung von n O(1) O(1) bleibt gleich O(log(n)) O(log(2n)) logarithmischer Anstieg O(n) O(2n) Verdopplung O(n * log(n)) O(2n * log(2n)) logarithmischer Anstieg O(n²) O(2n²) x4 O(2n) O(22𝑛 ) x32 Analog dazu die Verhundertfachung Theorie 8: Such- und Sortieralgorithmen „Was ist eine binäre Suche? Wie funktionieren Bubblesort, Mergesort und Quicksort? Wie hoch ist der Aufwand dafür im Durchschnitt und im schlechtesten Fall?“ Binäre Suche: Suchraum immer halbieren und dann entweder links oder rechts weitersuchen. Bubblesort: Bei der Suche wird die Eingabeliste von links nach rechts durchlaufen. Dabei werden immer die zwei Nachbarelemente miteinander verglichen. Falls das linke Nachbarelement größer als das rechte ist, werden die beiden getauscht. So wandert das größte Element immer weiter nach rechts. Dieser Vorgang wird so lange durchgeführt bis in einem Durchlauf keine Elemente mehr geordnet werden müssen. Mergesort: Hier wird die Liste immer durch zwei geteilt bis die „kleineren Listen“ nur noch ein Element haben. Danach wird jeweils ein Element aus einer Liste mit dem Element aus der kongruenten Liste verglichen und dann in der richtigen Reihenfolge wieder in die sortierte Liste eingefügt. Quicksort: Bei Quicksort wird zuerst ein Pivot-Element gewählt. Danach kommen alle Elemente, die kleiner gleich dem Pivot-Element sind in die linke Teilliste und alle die größer gleich dem Element sind in die rechte Teilliste. Danach werden die Teillisten wieder mit Quicksort sortiert, solange, bis die Liste geordnet ist. Dein Name Sortieralgorithmus Binäre Suche Mergesort Quicksort Bubblesort PK Aufgabenblatt #7 Aufwand (max.) O(log(n)) O(n*log(n)) O(n²) O(n²) 18.12.2013 Aufwand (avg.) O(log(n)) O(n*log(n)) O(n*log(n)) O(n²) Theorie 9: Generezität „Was unterscheidet generische von nicht-generischen Klassen? Was unterscheidet einen Typ von einem Typparameter? Kann man Typen und Typparameter gleich verwenden? Wie kann man in Java primitive Typen wie int als Elementtypen in generischen Containern verwenden?“ Generische Klassen haben einen Typparameter, anstatt eines Datentypes. Für diesen Typparameter kann später ein Typ (Integer, Boolean, CustomClass, …) eingesetzt werden. Ein Typparameter ist kein Typ sondern wird vom Compiler durch einen Typ ersetzt. Man kann Typen und Typparameter nicht gleich verwenden, da man Typparameter alleine nicht vergleichen kann, da nie klar ist durch welchen Typ der Parameter ersetzt wird. Zum Beispiel werden Fließkommazahlen unter Umständen anders verglichen als Integer-Werte. Man kann primitive Typen als Elementtypen in generischen Klassen verwenden, indem man den dazugehörigen Referenztyp angibt. Übergebene Typen werden dann automatisch durch Autoboxing in den entsprechend Referenztyp umgewandelt.