Algorithmen datenstrukturen
This presentation is the property of its rightful owner.
Sponsored Links
1 / 58

Algorithmen & Datenstrukturen PowerPoint PPT Presentation


  • 44 Views
  • Uploaded on
  • Presentation posted in: General

Sommersemester 2009. Algorithmen & Datenstrukturen. Prof. Dr. Peter Kneisel. Didaktik: Durchführung. Diese Vorlesung enthält Übungen Die Übungen werden je nach Bedarf durchgeführt. Zur Vorbereitung werden Übungsblätter, je nach Vorlesungsverlauf zusammengestellt.

Download Presentation

Algorithmen & Datenstrukturen

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.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Algorithmen datenstrukturen

Sommersemester 2009

Algorithmen &Datenstrukturen

Prof. Dr. Peter Kneisel


Didaktik durchf hrung

Didaktik: Durchführung

  • Diese Vorlesung enthält Übungen

    • Die Übungen werden je nach Bedarf durchgeführt.

    • Zur Vorbereitung werden Übungsblätter, je nach Vorlesungsverlauf zusammengestellt.

    • Weitere Übungen sind im Foliensatz vorhanden und sollten selbständig und vollständig bearbeitet werden.

  • Vorsicht !

    • Kommen Sie in alle Veranstaltungen - machen Sie die Übungen

    • … auch wenn vieles auf JAVA zugeschnitten ist, so sind die Konzepte verallgemeinbar und vielseitig zu verwenden – insb. seien mir syntaktische „Ungenauigkeiten“ verziehen und sogar zusätzclicher Ansporn für eigene konstruktive Verbesserungsvorschläge ;-)


Didaktik folien

Didaktik: Folien

  • Der Vorlesungsstoff wird anhand von Folien dargelegt

    • Die Folien bilden nur einen Rahmen für die Inhalte. Die Folien sollten daher mit Hilfe eigener Vorlesungsskizzen ergänzt werden - am besten in Form einer Vorlesungsnachbereitung max. 3 Tage nach der Vorlesung

    • Zusätzlich zu den Folien werden Beispiele an der Tafel oder am Rechner gezeigt. Diese sollten Sie vollständig mitskizzieren.

  • Zur vollständigen Nachbereitung, z.B. als Klausurvorbereitung, sind die Folien einheitlich strukturiert

    • Es gibt genau drei Gliederungsebenen: Kapitel, Unterkapitel, Abschnitte

    • Die Inhalte jedes Kapitels und jedes Unterkapitels werden jeweils motiviert und sind verbal beschrieben. Zusätzlich gibt es jeweils ein stichwortartiges Inhaltsverzeichnis der Unterkapitel, bzw. Abschnitte

  • Die Vorlesung wird ständig überarbeitet, so dass sich die Foliensätze ändern können (und werden)

    • Laden Sie sich zur endgültigen vollständigen Klausurvorbereitung nochmals zusätzlich den kompletten Foliensatz herunter.


Literatur

Literatur

  • Diese Veranstaltung ist anhand (wirklich) vieler Bücher und einer Menge eigener Erfahrungen erstellt worden. Jedes Buch hat dabei Schwerpunkte in speziellen Bereichen und ist daher sinnvoll. Eine Auflistung aller dieser Bücher ist nicht sinnvoll.Stellvertretend für all diese Bücher sei hier ein Buch angeführt:

    • Robert Sedgewick: „Algorithmen in Java: Teil 1-4“; Addison-Wesley 2003

      viele Programmierbeispiele sind aus:

    • G.Saake, K.-U. Sattler: „Algorithmen & Datenstrukturen: Eine Einführung mit Java“, dpunkt.verlag, 2002

      der Klassiker ist:

    • N.Wirth: „Algorithmen & Datenstrukturen“, Teubner, 1979

  • Motivation ist alles !Haben Sie meine Empfehlungen aus dem ersten Semester beherzigt ?

    • S.Singh: „Fermats letzter Satz“; DTV, 9.Auflage 2004

    • M. Spitzer: „Geist im Netz“; Spektrum, Akad. Verlag 2000

    • H. Lyre: „Informationstheorie“; UTB, 2002

    • A.Hodges: „Alan Turing, Enigma“; Springer-Verlag, 1983

    • D.R.Hofstadter: „Gödel, Escher, Bach“; Klett-Cotta, 2006 (Taschenbuch 1991)


Inhalt

Inhalt

  • In „Grundlagen der Informatik“ haben wir uns mit zwei grundlegenden Aspekte der Informatik befasst:

    • Was ist Information und wie kann man diese auf höheren semantischen Ebenen strukturieren.

    • Aus welchen einfachen Elementen ist ein (imperativer) Algorithmus aufgebaut

  • „Algorithmen & Datenstrukturen“ nimmt diese Zweiteilung auf:

    • Zunächst werden wir die semantische Leiter nach oben steigen und komplexere semantische Strukturen kennenlernen, die grundlegend für Lösungen viele typische Problemstellungen sind.

    • Anschließend werden wir die wichtigsten Algorithmen kennenlernen, die auf diesen Strukturen arbeiten.

  • Inhalt

    • Abstrakte Datentypen (ADTs)

    • Suchen:Grundlagen, Algorithmus, Analyse

    • SortierenGrundlagen, Algorithmus, Analyse


Berblick und einordnung

Überblick und Einordnung

Sortieren

Suchen

ADTs

A&D

PIS

Statik, Struktur

Dynamik, Algorithmik

Datenstrukturen

Komplexität

Zahlen

Verifikation

Zeichen

Strukturierung

Codes

Elemente

Information

OOP

GDI

RA


Kapitel 1 abstrakte datentypen adts

Kapitel 1Abstrakte Datentypen (ADTs)

  • In „Grundlagen der Informatik“ haben wir elementare Strukturen kennengelernt und gesehen, wie daraus mit komplexeren Strukturierungsverfahren komplexere Strukturen aufgebaut werden können.Wir haben uns dabei genau auf die Strukturen beschränkt, die den meisten imperativen Programmiersprachen gemeinsam sind.In diesem Kapitel gehen wir nun in semantisch höhere Ebenen und erläutern Strukturen, die häufig verwendet werden, aber nicht im Sprachumfang der meisten Programmiersprachen liegen (sehr wohl aber in Klassenbibliotheken)

  • Inhalt

    • Wiederholung

    • Was sind ADTs

    • Stacks (Kellerspeicher, Stapel)

    • Queues (Warteschlangen)

    • Einfach verkettete Listen

    • Zweifach verkettete Listen

    • Hashlisten

    • Bäume

    • Graphen

    • Frameworks


1 1 wiederholung

1.1Wiederholung

  • Wir haben bereits in „Grundlagen der Informatik“ einiges über die Beziehung von Datentypen erfahren.Was, wird hier kurz zusammengefasst

  • Datenstrukturen

  • Datentypen

  • KLassifikation von Datentypen


1 1 1 datenstrukturen

1.1.1Datenstrukturen

  • In der Informatik werden Objekte der realen oder abstrakten Welt erfasst

    • Bei der Erfassung beschränkt man sich möglichst auf die für den weiteren Transport / Speicherung/Verarbeitung/Umsetzung notwendige Information

  • Zur internen Repräsentation werden diese Objekte abstrahiert

    • Zur Abstraktion gehört die Erkennung von Strukturen - zunächst im Sinne einer Aggregation.

    • Also

      • Aus welchen Teilobjekten bestehen Objekte ?

      • In welchem Verhältnis stehen die Teilobjekte zueinander ?

      • Welches sind die „atomaren“ Teilobjekte ?

    • es existieren noch weitere strukturelle Beziehungen (z.B. Vererbung)

  • Anschließend werden diese Objekte typisiert.

    • Typisierung ist die Einteilung von abstrakten internen Objekten in Gruppen mit gleichen oder ähnlichen Eigenschaften.


1 1 2 datentypen

Typen sind also nicht die intern repräsentierten Objekte, sondern beschreiben die Eigenschaft einer Gruppe von Objekten.

Zu diesen Eigenschaften gehören:

Struktur

Wertebereich

anwendbare Operatoren, Funktionen, Relationen

Beziehungen zu anderen Typen

interne Repräsentationsweise

Einige Anmerkungen::

Der Begriff „Datentyp“ ist weitergehend als der Begriff „Datenstruktur“

In der Objektorientierten Programmierung wird statt „Datentyp“ auch der Begriff „Klasse“ verwendet (Klassen beschreiben mehr Eigenschaften)

Konkrete Repräsentanten eines Datentyps werden (u.a) „Variable“ oder- bei OO-Sprachen - „Instanz“ genannt

1.1.2Datentypen

Beispiel:

Imaginäre Zahlen


1 1 3 klassifikation der datentypen

Boolean

(Wahrheitswert)

Integer(Ganzzahl)

Char (Zeichen)

Enumeration (Aufzählung)

1.1.3Klassifikation der Datentypen

Datentypen

Konkrete

Abstrakte

Idealisierte

Einfache

Pointer(Zeiger)

Strukturierte

...

Ordinale

Real

(Fließkomma)

Array (Feld)

Record (Verbund)

Union(Variantenverb.)

...


1 1 3 erl uterung der klassifikation

13

insert (Element)

6

61

delete (Element)

search (Element)

2

12

15

79

1.1.3Erläuterung der Klassifikation

  • Idealisierte Datentypen

    • aus der Mathematik bekannte Datentypen: R, N, Z, ...

    • Variablen dieser Typen sind oft nicht endlich darstellbar (Bsp: 2)

    • In einem Computer-Algebra-System symbolisch darstellbar (Bsp: 2^( 1/2))

  • Konkrete Datentypen

    • in einem Rechner von Hard- oder Software bereitgestellte Datentypen

    • entweder vordefiniert oder durch den Benutzer definierbar

  • Abstrakte Datentypen

    • verbergen ihren inneren Aufbau vor dem Benutzer

    • bestehen aus beliebigen Strukturen über konkrete/idealisierte Datentypen, sowie aus Zugriffsfunktionen bzw. Prozeduren

    • Beispiel:Baum


1 2 was sind adts

1.2Was sind ADTs

  • „Ein abstrakter Datentyp fasst die wesentlichen Eigenschaften und Operationen einer Datenstruktur zusammen, ohne auf deren eigentlichen Realisierung im Rechner einzugehen“Konkrete Datentypen werden aus ordinalen (Basis-) Datentypen konstruiert und sind somit direkt in einer Implementierung einsetzbar.

  • Grundsätze

  • Algebren

  • Signaturen

  • Axiome

  • Beispiel einer ADT-Schnittstelle

  • Anwendung: Tabelle


1 2 1 grunds tze

1.2.1Grundsätze

  • Kapselung:Ein abstrakter Datentyp darf nur über seine Schnittstellen benutzt werden.Das bedeutet insbesondere,

    • dass interne Strukturen von außen nicht direkt zugreifbar sind

    • dass interne Strukturen, die nicht über Operationen der Schnittselle zugreifbar sind, gar nicht von außen zugegriffen werden können.

  • Geheimnisprinzip:Die interne Realisierung eines abstrakten Datentyps ist verborgen.Das bedeutet insbesondere,

    • dass konkrete Umsetzungen von ADTs sehr stark von der verwendeten Programmiersprache und der geplanten Verwendung abhängen.

  • Diese Prinzipen der Kapselung und des Geheimnisprinzips wurden schon in frühen rein prozeduralen imperativen Programmiersprachen gefordert, aber erst mit der Einführung objektorientierter imperativer Programmiersprachen ducrh Sprachkonstrukte mehr oder weniger erzwungen.

    • In Pascal konnte man Teilstrukturen eines abstrakten Datentyps jederzeit auch von außen zugreifen. Die möglichen Operation waren sprachlich nicht mit den Strukturen verknüpft.

    • In Java werden Datenstrukturen als „private“ vor Zugriffen von außen geschützt und Operationen in Methoden „geheim“ realisiert.


1 2 2 algebren

1.2.2Algebren

  • Datentypen (auch abstrakte) lassen sich mathematisch als „Algebren“ betrachten ( Vorlesung „Diskrete Strukturen“)

    • Eine Algebra ist definiert durch Wertemengen und die Operatoren, die man darauf anwenden kann.

  • Bsp: Betrachten Sie die natürlichen Zahlen.

    • darauf lassen sich (zunächst) die Operatoren: +, -, x und % (ganzahliges Teilen) anwenden, als Ergebnis bekommen Sie Werte aus der Wertemenge der natürlichen Zahlen

    • Sie können aber auch Vergleichsoperatoren: >, <, ==, != anwenden, dann bekommen Sie als Ergebnis Werte einer anderen Wertemenge, die der bool‘sche Zahlen: true, false,

    • Sie können nun auf die Wertemenge der bool‘schen Werte auch bool‘sche Operatoren anwenden: , ,  als Ergebnis bekommen Sie wieder bool‘sche Werte.

    • Ihre gesamte Algebra verwendet also zwei Sorten von Datenstrukturen (mehrsortige Algebra): natürliche Zahlen und bool‘sche Werte und kann darauf unterschiedliche Operatoren anwenden: +, -, x, %, >, <, ==, !=, , ,  wobei nicht jeder Operator auf jeden Wert (oder Wertepaar) anwendbar ist.

  • Eine Algebra ist also definiert durch ihre Sorten, die Operationen und die Art, wie diese Operationen auf Werte der Sorten anwendbar sind.


1 2 3 signaturen

1.2.3Signaturen

  • Die Schnittstellen eines (A)DTs - also die Art, wie man den (A)DT verwendet -lassen sich durch seine Signatur beschreiben.

  • Bsp: betrachten Sie den Datentyp integer:

    • integer unterstützt/erzeugt zwei Sorten: integer und bool

    • integer unterstützt die Operatoren:const : integer // nullstelliger Operator: Konstantesuccessor : integer integer // einstellige Operation+, -, x, % : integer  integer integer // zweistellige Operation >, <, ==, != : integer  integer bool // zweistellige Operation,  : bool  bool bool // zweistellige Operation : bool bool // einstellige Operation

  • Diese Formalisierung einer Algebra beschreibt die Strukturen und die Operationen eines (abstrakten) Datentyps und wird Signatur des Datentyps genannt.Aus der Signatur eines (A)DTs geht also insbesonder hervor:

    • Dessen Wertebereiche in den unterschiedlichen Sorten

    • Die Operatoren und deren Stelligkeit

    • Die Wertebereiche der bei den Operationen verwendeten Operanten


1 2 4 axiome

1.2.4Axiome

  • Selbst wenn Sie die Signatur eines (A)DT kennen, wissen Sie zwar welche Operatoren auf welche Wertebereiche (Sorten) anzuwenden sind, Sie wissen aber immer noch nicht wie die Werte durch die Operatoren verändert werden:Das beschrieben Sie mit Axiomen.

  • Bsp.: Betrachten Sie die natürlichen Zahlen, so gilt z.B. für die Addition folgendes Axiom:

    + (i,0) = i

    + (i,successor (j)) = succesor (+ (i,j))

  • Entsprechend lassen sich für alle Operatoren Axiome aufstellen. Damit ergibt sich als Spezifikation für den ADT integer: (in Pseudo-Notation)

    type: integer // implizit auch verwendbare Sorte

    import: boolean // Sorten, die zusätzlich verwendet werden

    operators:

    +, -, x, % : integer  integer integer

    ...

    axioms:  i,j : integer

    + (i,0) = i

    + (i,successor (j)) = succesor (+ (i,j))

    ...


1 2 5 beispiel einer adt schnittstelle

1.2.5Beispiel einer ADT-Schnittstelle

type: list(T) // T ist die Wertemenge der Elemente

// T ist ein sog. Sortenparameter

import: integer

operators:

[] : list

_ : _ : T x list list // erweitert Liste

// _ : _ ist Infix-Operator

head : list T // Kopf der Liste

tail : list  list // Liste ohne Kopf

length : list  integer // Anzahl Listenelemente

axioms:  l : list,  x : T

head ( x : l ) = x

tail ( x : l ) = l

lenght ( [] ) = 0 // [] ist leere Liste

length ( x : l ) = successor ( length (l) )


1 2 6 anwendung tabellen

1.2.6Anwendung: Tabellen

  • Listen repräsentieren oft „Tabellen“:

    • Definition:Eine Tabelle o der Größe n ist eine Folge (z.B. Liste) von n Elementen gleichen Typs o = (o1, o2, … , on)

  • Oft sind die Elemente einer Tabelle nochmals in zwei Teile unterstruktiert:

    • Schlüssel-Daten (key)Die Schlüsseldaten bezeichnen (oft eindeutig) das Element einer Liste.Der Key kann nochmals unterstrukturiert sein.

    • Informations-Daten (info)Die Informations-Daten geben für das durch den key bezeichnete Element zusätzliche Informationen an.Auch info kann nochmals unterstrukturiert sein.

key1

info1

Anmerkung:Da die Indizierung von Listen in

vielen Programmiersprachen mit

„0“ beginnt, man aber in der realen

Welt mit „1“ zu zählen beginnt, wird

das „0“-te Element oft als Dummy-

Element mit einem Dummy-Wert

versehen und ignoriert.

key2

info2

keyn

infon


1 3 stacks kellerspeicher stapel

1.3.Stacks (Kellerspeicher, Stapel)

  • Stacks (Kellerspeicher, Stapel) sind einfache Abstraktionen von Strukturen, die in vielen Bereichen der Informatik, insbesondere aber in den systemnahen Bereichen verwendet werden.Stacks bezeichnet man manchmal auch als LIFO (Last in – First Out)-Schlangen

  • Spezifikation

  • Implementierung

  • Die Java-Klasse „stack“


1 3 1 spezifikation

1.3.1Spezifikation

type: stack(T) // T ist die Wertemenge der Elemente

import: boolean

operators:

empty : stack // erzeugt leeren Stack

push : stack x T stack // Legt Element auf Stack

pop : stack stack // nimmt Element von Stack

top : stack  T // zeigt oberstes Element an

is_empty : stack  boolean // ist Stack leer ?

axions:  s : stack,  x : T

pop (push (s,x)) = s

top (push (s,x)) = x

is_empty (empty) = true // empty ist Wert des Stack

is_empty (push (s,x)) = false


1 3 2 implementierung eines stacks

1.3.2Implementierung eines Stacks

public class ArrayStack implements Stack {

private Object elements[] = null; // Elemente

private int num = 0; // aktuelle Anzahl

// Stack mit vorgegebener Größe erzeugen

public ArrayStack(int size) {

elements = new Object[size];

}

// Abfrage auf leeren Stack

public boolean isEmpty() {

return num == 0;

}

public void push(Object obj) throws StackException {

if (num == elements.length)

// KapazitŠt erschöpft

throw new StackException();

elements[num++] = obj;

}

public Object pop() throws StackException {

if (isEmpty()) // Stack ist leer

throw new StackException();

Object o = elements[--num];

elements[num] = null;

return o;

}

public Object top() throws StackException {

if (isEmpty()) // Stack ist leer

throw new StackException();

return elements[num - 1];

}

}


1 3 3 die java klasse stack

1.3.3Die Java-Klasse „stack“

import java.util.*;

public class StackExample {

public static void main(String[] args)

{

Stack s = new Stack(); // ohne Parameter

s.push("Erstes Element"); // Rückgabewert: eingefügtes Element ...

s.push("Zweites Element"); // ... wird ignoriert

s.push("Drittes Element");

while (true) {

try {

System.out.println(s.pop()); // ?peek() würde Element entfernen

} catch (EmptyStackException e) { // wird beim Lesezugriff auf ...

break; // ... leeren Stack geworfen

}

}

}

}


1 4 queues

1.4.Queues

  • Queues (Warteschlangen) sind lineare Listen, deren Elemente nach dem FIFO-Prinzip (First in–First Out) ein- bzw. ausgefügt werden Auch Queues kommen in systemnahen Bereichen vor, insbesondere bei Betriebssystemen.

  • Spezifikation

  • Implementierung einer Queue

  • Die Java-Klasse „queue“


1 4 1 spezifikation

1.4.1Spezifikation

type: queue(T) // T ist die Wertemenge der Elemente

import: boolean

operators:

empty : queue // erzeugt leere Queue

enter : queue x T queue // stellt Element ans Ende der Queue

leave : queue queue // nimmt erstes Element von Queue

front : queue  T // zeigt erstes Element der Queue

is_empty : queue  boolean // Ist Queue leer ?

axions:  q : queue,  x : T // empty ist der Wert einer leeren queue

leave (enter (empty,x)) = empty

// (x) ohne Kopf = empty

leave (enter (enter(q,x),y)) = enter (leave (enter (q,x)), y)

// (q,x,y) ohne Kopf = (q,x) ohne Kopf + y -> ((q,x) ohne Kopf,y)

front (enter (empty,x)) = x

// Kopf von (x) = x

front (enter (enter(q,x), y)) = front (enter (q,x))

// Kopf von (q,x,y) = Kopf von (q,x)

is_empty (empty) = true // is_empty von empty ist true

is_empty (enter(q,x)) = false // is_empty von (q,x) ist falsch


1 4 2 implementierung einer queue

1.4.2Implementierung einer Queue

public class ArrayQueue implements Queue {

private Object[] elements; // Elemente

private int l = 0; // „lower“ Zeiger

private int u = 0; // „upper“ Zeiger

// in der Queue sind max. size-1 Elemente

// Queue mit vorgegebener Länge erzeugen

public ArrayQueue (int size) {

elements = new Object[size];

}

public boolean isEmpty () {

return l == u;

}

// Zeige das lower Element

public Object front () throws QueueException {

if (isEmpty ())

throw new QueueException ();

return elements[l];

}

// Einfügen eines Elementes

public void enter (Object obj) throws QueueException {

if ((elements.length - l + u) % elements.length

== elements.length - 1)

// Kapazität ist erschöpft (= size-1)

throw new QueueException ();

elements[u] = obj;

// oberen Zeiger aktualisieren

u = (u + 1) % elements.length;

// Modulo, da array zyklisch verwendet.

}

// Herausnehmen des lower-Elementes

public Object leave () throws QueueException {

if (isEmpty ())

throw new QueueException ();

Object obj = elements[l];

elements[l] = null;

// unteren Zeiger aktualisieren

l = (l + 1) % elements.length;

return obj;

}

}


1 4 3 die java klasse queue

1.4.3Die Java-Klasse „queue“

import java.util.*;

public class QueueExample {

public static void main(String[] args)

{

Queue<String> queue = new LinkedList<String>(); // <...> gibt den Typ

// von Elementen an

queue.offer( "Fischers" );

queue.offer( "Fritze" );

queue.offer( "fischt" );

queue.offer( "frische" );

queue.offer( "Fische" );

queue.poll();

queue.offer( "Nein, es war Paul!" );

while ( !queue.isEmpty() )

System.out.println( queue.poll() );

}

}

// und es gibt noch einige weitere Queues in java.util.*


1 5 einfach verkettete liste

1.5Einfach verkettete Liste

  • Listen sind (ziemlich) simple Datentypen, die sich statisch durch den konkreten strukturierten Datentyp „array (Feld)“ darstellen lässt und damit in den meisten Programmiersprachen implizit vorhanden ist.In der nicht-imperativen Programmiersprache LISP ist „Liste“ zudem der einzige strukturierte Datentyp.Möchte man die Länge einer Liste jedoch zur Laufzeit eines Programmes dynamisch verändern so muss man auf eigenen Umsetzungen mithilfe eines ADTs zurückgreifen.

  • class

  • main

  • Methoden

  • Implementierung als Liste


1 5 1 class

1.5.1class

public class List {

static class Node {

Object obj;

Node next;

public Node(Object o, Node n) { obj = o; next = n; }

public Node() { obj = null; next = null; }

public void setElement(Object o) { obj = o; }

public Object getElement() { return obj; }

public void setNext(Node n) { next = n; }

public Node getNext() { return next; }

}

private Node head = null;

public List() {}

public void addFirst(Object o) {}

public void addLast(Object o) {}

public Object getFirst() throws ListEmptyException {}

public Object getLast() throws ListEmptyException {}

public Object removeFirst() throws ListEmptyException {}

public Object removeLast() throws ListEmptyException {}

public int size() {}

public boolean isEmpty() {}

}


1 5 2 main

1.5.2main

public static void main(String args[]) {

List lst = new List();

lst.addFirst("Drei");

lst.addFirst("Zwei");

lst.addFirst("Eins");

lst.addLast("Vier");

lst.addLast("Fünf");

lst.addLast("Sechs");

while (! lst.isEmpty()) {

System.out.println((String) lst.removeFirst());

}

}


1 5 3 methoden

1.5.3Methoden

public List() {

head = new Node();

}

public void addFirst(Object o) {

Node n = new Node(o, head.getNext());

head.setNext(n);

}

public Object getFirst() throws ListEmptyException

{

if (isEmpty())

throw new ListEmptyException();

return head.getNext().getElement();

}

public void addLast(Object o) {

Node l = head;

while (l.getNext() != null)

l = l.getNext();

Node n = new Node(o, null);

l.setNext(n);

}

public Object removeFirst() throws ListEmptyException {

if (isEmpty())

throw new ListEmptyException();

Object o = head.getNext().getElement();

head.setNext(head.getNext().getNext());

return o;

}

public Object removeLast() throws ListEmptyException {

if (isEmpty())

throw new ListEmptyException();

Node l = head;

while (l.getNext().getNext() != null)

l = l.getNext();

Object o = l.getNext().getElement();

l.setNext(null);

return o;

}


1 5 4 implementierung als liste

1.5.4Implementierung als Liste

public class ListStack implements Stack {

private List list; // Liste zur Verwaltung der Elemente

public ListStack () {

list = new List ();

}

public void push (Object obj) {

// Element vorn anfŸgen

list.addFirst (obj);

}

public Object pop () throws StackException {

if (isEmpty ())

throw new StackException ();

// Element von vorn entfernen

return list.removeFirst ();

}

public Object top () throws StackException {

if (isEmpty ())

throw new StackException ();

return list.getFirst ();

}

public boolean isEmpty () {

return list.isEmpty ();

}

}


1 6 zweifach verkettete liste

1.6Zweifach verkettete Liste

  • Aus bestimmten Gründen – vor allem Laufzeit-Effizienz – verwendet man oft Listen, deren einzelne Elemente nicht nur den jeweiligen Nachfolger, sondern auch den jeweiligen Vorgänger kennen.Diese Listen nennt man das „Zweifach bzw. Doppelt verkettete Listen“

  • class

  • iterator

  • main

  • Methoden


1 6 1 class

1.6.1class

public class DList {

static class Node {

Object obj;

Node prev, next;

public Node (Object o, Node p, Node n) { obj = o; prev = p; next = n; }

public Node () { obj = null; prev = next = null; }

...

// Setter und Getter-Methoden

public void setElement (Object o) { obj = o; }

public Object getElement () { return obj; }

public void setNext (Node n) { next = n; }

public Node getNext () { return next; }

public void setPrevious (Node p) { prev = p; }

public Node getPrevious () { return prev; }

}

private Node head = null;

private Node tail = null;

...

public java.util.Iterator iterator () {}

}


1 6 2 iterator

1.6.2iterator

class ListIterator implements java.util.Iterator {

private Node node = null;

public ListIterator () {

node = head.getNext();

}

public boolean hasNext () {

return node.getNext () != tail;

}

public void remove () {

throw new UnsupportedOperationException ();

}

public Object next () {

if (! hasNext ())

throw new java.util.NoSuchElementException ();

Object o = node.getElement ();

node = node.getNext ();

return o;

}

}


1 6 3 main

1.6.3main

public static void main (String args[]) {

DList lst = new DList ();

java.util.Iterator it = lst.iterator ();

while (it.hasNext ()) {

System.out.println ((String) it.next ());

}

lst.addFirst ("Drei");

lst.addFirst ("Zwei");

lst.addFirst ("Eins");

lst.addLast ("Vier");

lst.addLast ("Fünf");

lst.addLast ("Sechs");

it = lst.iterator ();

while (it.hasNext ()) {

System.out.println ((String) it.next ());

}

}


1 6 4 methoden

1.6.4Methoden

public DList () {

head = new Node ();

tail = new Node ();

head.setNext(tail);

tail.setPrevious(head);

tail.setNext(tail);

}

public void addFirst (Object o) {

Node n = new Node (o, head, head.getNext());

head.getNext ().setPrevious (n);

head.setNext (n);

}

public Object getFirst () throws ListEmptyException {

if (isEmpty ())

throw new ListEmptyException ();

return head.getNext ().getElement ();

}

public void addLast (Object o) {

Node l = tail.getPrevious ();

Node n = new Node (o, l, tail);

l.setNext (n);

tail.setPrevious (n);

}

public Object removeFirst () throws ListEmptyException {

if (isEmpty ())

throw new ListEmptyException ();

Object o = head.getNext ().getElement ();

head.setNext (head.getNext ().getNext ());

head.getNext ().setPrevious (head);

return o;

}

public Object removeLast () throws ListEmptyException {

if (isEmpty ())

throw new ListEmptyException ();

Node n = tail.getPrevious ();

n.getPrevious ().setNext (tail);

tail.setPrevious (n.getPrevious ());

return n.getElement ();

}


1 7 hashlisten

1.7Hashlisten

  • Hashlisten sind Listenstrukturen, manchmal erweitert durch „weitere“ Strukturen, die sich sehr gut für das Suchen eignen ( Kapitel 2).Hier seien die grundlegenden Ideen des Hashens dargestellt.

  • Grundprinzip des Hashens

  • Die Hashfunktion

  • Behandlung von Kollisionen

  • Implementierung einer Hashliste


1 7 1 grundprinzipien des hashens

1.7.1Grundprinzipien des Hashens

  • Das Hashen basiert auf drei Grundprinzipien:

    • Die Speicherung der Datensätze erfolgt in einem Feld mit Indexwerten von 0 bis n-1. wobei die einzelnen Positionen als „Buckets“ (Eimer) bezeichnet werden.

    • Eine Hashfunktion h bestimmt für ein zu speicherndes Element e dessen Position h(e) im Feld

    • Diese Hashfunktion h sorgt für eine „gute“ – im besten Fall kollisionsfreie, d.h. injektive (meist aber „Nur“ kollisionsarme) Abbildung d.h. Verteilung der zu speichernden Elemente.

  • Da normalerweise der Wertebereich der möglicherweise zu speichernden Element größer ist als die Anzahl der Elemente in der Hashliste kann die Funktion h (meist) nicht für alle Werte n eindeutige Hashwerte h(n) liefern.Das führt zu Kollisionen, deren Behandlung die „Qualität“ eines Hashverfahrens ausmacht.

  • Ist die Hashfunktion ungeschickt gewählt, kann das Verfahren „entarten“, was zu teilweise dramatischen Geschwindigkeitsverlusten führen kann.


1 7 2 die hashfunktion

1.7.2Die Hashfunktion

  • Die Auswahl der Hashfunktion h hängt natürlich vom zu speichernden Datentyp (bzw. dessen Wertebereich) und der Auftrittswahrscheinlichkeit der Werte ab.

  • Für Integerwerte i wird oft die Modulofunktion verwendet:

    • h(i) = i mod n (wobei n die größe der Hashliste ist)

      Diese Funktion funktioniert in der Regel nur für große primzahlige n gut(inbesondere ist n = 2x nicht gut !)

      Beispiel: h(i) = i mod 7Index 0 1 2 3 4 5 6Element 28 36 16 66 25 75 27 (danach führt jedes Element zu Kollision)

  • Für andere Datentypen kann eine Abbildung auf Integerwerte erfolgen:

    • Bei Fließkommazahlen kann man z.B. Mantisse und Exponent addieren

    • Bei Strings kann man den ASCII oder Unicode der einzelnen Buchstaben, eventuell mit einem Faktor gewichtet, miteinander addieren.

  • Meist ist eine Gleichverteilung der Bildbereiches der Hashfunktion wünschenswert, so dass man sich bestimmte Eigenschaften (z.B. ungleichgewichtige Verteilungen) des Urbildes zu Nutze machen kann und sollte.Andererseits geht die Komplexität der Hashfunktion h multiplikativ in die Gesamtkomplexität ein und sollte daher einfach gehalten werden.


1 7 3 behandlung von kollisionen

1.7.3Behandlung von Kollisionen

  • Führt die Hashfunktion für unterschiedlich Werte des Urbildes auf gleiche Hashwerte, so spricht man von Kollision, die man z.B. mit folgenden Verfahren behandeln kann:

    • Verkettung der Überläufer:Man erweitert die eindimensionale Listenstruktur der Hashliste um eine zweite Dimension (z.B. durch eine einfach verkettete Liste), in die man die kollidierenden Werte ablegt

    • Sondieren:Man legt den kollidierenden Wert an ein andere Stelle in der Hashliste ab, die sich durch die Berechnung eines Offsets ergeben:

      • beim linearen Sondieren wird die nächste freie Position verwendet.(also als Offset die Werte 1,2,3,4, …)

      • beim quadratischen Sondieren ergibt sich der mögliche Offset durch die Quadratzahlen (also 1,4,9,16,25, …).Dadurch wir d die „Klumpenbildung“, zu der das lineare Sondieren neigt, vermieden.


1 7 4 implementierung einer hashliste

1.7.4Implementierung einer Hashliste

publicclassHashTable {

Object[] table;

publicHashTable (intsize) {

table = newObject [size];

}

// fügt Element in Hashliste

publicvoidadd (Object o) {

intidx, oidx;

// berechnen Hashfunktion

oidx = idx = (o.hashCode () &

0x7fffffff) % table.length;

// falls Kollision -> suche nächstes Freies

while (table[idx] != null) {

idx = ++idx % table.length;

// fall Suche erfolglos -> Fehler

if (idx == oidx)

thrownewHashTableOverflowException ();

}

// trage Wert ein

table[idx] = o;

}

// sucht Element in Hashliste

publicbooleancontains (Object o) {

intidx, oidx;

oidx = idx = (o.hashCode () &

0x7fffffff) % table.length;

while (table[idx] != null) {

if (o.equals (table[idx]))

returntrue;

idx = ++idx % table.length;

if (idx == oidx)

break;

}

returnfalse;

}

publicstaticvoidmain (String[] args) {

HashTabletbl = newHashTable (20);

tbl.add („Au");

tbl.add („Oh");

tbl.add („Ah");

System.out.println (tbl.contains („Ah"));

System.out.println (tbl.contains („Be"));

}

}


1 8 b ume

1.8Bäume

  • Bäume sind (zumindest) zweidimensionale Strukturen, die viele reale Strukturen abzubilden Vermögen und zudem sehr gut zum Durchsuchen geeignet sind.Es gibt daher sehr viele spezielle Arten von Bäumen, von denen hier stellvertretend vor allem die binären Bäume behandelt werden sollen.

  • Definitionen & Beispiele

  • Spezifikation

  • Datentypen

  • Traversierung

  • Weitere Bäume


1 8 1 definitionen beispiele

1.8.1.Definitionen & Beispiele

  • Ein Baum ist eine Menge von Knoten und (gerichteten) Kanten mit folgenden Eigenschaften:

    • Ein ausgezeichneter Knoten wird als Wurzel bezeichnet

    • Jeder Knoten (außer der Wurzel) ist durch genau eine Kante mit seinem Vorgängerknoten verbunden (Vaterknoten, Elternknoten).Dieser Knoten wird dann auch als Kind (Sohn, Nachfolger) bezeichnet.

    • Ein Knoten ohne Kinder heißt Blatt

    • Knoten mit Kindern heißen innere Knoten

… nich‘ so praktisch

… wie sich derInformatiker einen

Baum vorstellt


1 8 1 definitionen beispiele1

1.8.1.Definitionen & Beispiele

  • Ein Pfad in einem Baum ist eine Folge von unterschiedlichen Knoten, in der die aufeinanderfolgenden Knoten durch Kanten verbunden sind

    • Zwischen jedem Knoten und der Wurzel gibt es genau einen Pfad

    • Dies bedeutet, dass ein Baum zusammenhängend ist und keine Zyklen besitzt

  • Unter dem der Niveau (der Tiefe) eines Knotens versteht man die Länge dessen Pfades zu der Wurzel

  • Die Höhe (Tiefe) eines Baumes entspricht dem maximalen Niveau einesBlattes + 1 („+1“ da die Wurzel mitzählt)

  • Je nach Art und Anzahl von Kindern unterscheidet man zwischen

    • n-ären Bäumen, wenn die maximale Anzahl von Kindern gleich n ist(also z.B. binärer Baum, wenn die maximale Anzahl der Kinder gleich 2 ist)

    • geordneten Bäumen, wenn die Kinder entsprechend einer Ordnungsrelation (z.B. von links nach rechts) angeordnet sind

Tiefe 0

Tiefe 1

((1+2)*3)+(2+5)

Tiefe 2

Tiefe 3


1 8 2 bin re b ume spezifikation

1.8.2.Binäre Bäume: Spezifikation

type: tree (T) // T ist die Wertemenge der Elemente

import: boolean

operators:

empty : tree // erzeugt leeren Baum

// verbindet zwei Bäume über neue Wurzel T

bin : tree x T x tree tree

left : tree tree // liefert den linken Teilbaum

right : tree tree // liefert den rechten Teilbaum

value : tree  T // liefert die Wurzel

is_empty : tree  boolean // ist Baum leer ?

axions:  s : stack,  x : T

left (bin (x,b,y)) = x // linker Teilbaum

right (bin (x,b,y)) = y // rechter Teilbaum

value (bin (x,b,y)) = b // Wurzel

is_empty (empty) = true // empty ist Wert des Baums

is_empty (bin (x,b,y)) = false


1 8 3 bin re b ume datentypen

1.8.3Binäre Bäume: Datentypen

staticclassTreeNode {

Objectkey; // Wert des Knotens

TreeNodeleft = null; // Referenz auf linken Teilbaum

TreeNoderight = null; // Referenz auf rechten Teilbaum

// Konstruktor

publicTreeNode (Object e) { key = e; }

// getter Methoden

publicTreeNodegetLeft () { returnleft; }

publicTreeNodegetRight () { returnright; }

publicObjectgetKey () { returnkey; }

// setter Methoden

publicvoidsetLeft (TreeNode n) { left = n; }

publicvoidsetRight (TreeNode n) { right = n; }

}

staticclassBinaryTree {

protectedTreeNoderoot = null;

publicBinaryTree () { }

publicBinaryTree (TreeNode n) { root = n; }

}

TreeNode e1 = newTreeNode(“+“);

e1.setleft (newTreeNode(“1“));

e1.setright (newTreeNode(“2“));

TreeNode e2 = newTreeNode(“*“);

e2.setleft (e1);

e2.setright (newTreeNode(“3“));

TreeNode e3 = newTreeNode(“+“);

e3.setleft (newTreeNode(“2“));

e3.setright (newTreeNode(“5“));

TreeNode e = newTreeNode(“+“);

e.setleft (e2);

e.setright (e3);

 Bäume baut man „von unten nach oben“ auf


1 8 4 bin re b ume traversierung

1.8.4Binäre Bäume: Traversierung

  • Je nach Reihenfolge unterschiedet man beim Baumdurchlauf folgende Traversierungsarten.

    • Inorder: Hier wird zuerst rekursiv der linke Teilbaum, danach der Knoten selbst, und schließlich der rechte Teilbaum durchlaufen.

    • Preorder: Hier wird zuerst der Knoten, danach zunächst rekursiv der linke Teilbaum und schließlich rekursiv der rechte Teilbaum durchlaufen.

    • Postorder: Hier wird zuerst rekursiv der linke Teilbaum, danach rekursiv der rechte Teilbaum, schließlich der Knoten durchlaufen.

      Diese Traversierungsarten gehen also für jeden Knoten rekursiv in die Tiefen der beiden Teilbäume und können daher auch Tiefentraversierung genannt werden.Daneben gibt es noch eine Traversierungsart, die auf jedem Niveau alle Knoten berücksicht. Diese Breitentraversierung nennt man:

    • Levelorder: erst werden alle Knoten eines Niveaus durchlaufen, danach rekursiv die beiden Teilbäume

Inorder:1 + 2 * 3 + 2 + 5

Preoder: + * + 1 2 3 + 2 5

Postorder:1 2 + 3 * 2 5 + + ( UPN)

Levelorder:+ * + + 3 2 5 1 2


1 8 4 bin re b ume traversierung1

1.8.4Binäre Bäume: Traversierung

private voidprintPreorder (TreeNode n) {

if (n != nullNode) {

System.out.println (n.toString ());

printPreorder (n.getLeft ());

printPreorder (n.getRight ());

}

}

private voidprintPostorder (TreeNode n) {

if (n != nullNode) {

printPostorder (n.getLeft ());

printPostorder (n.getRight ());

System.out.println (n.toString ());

}

}

protectedvoidprintInorder (TreeNode n) {

if (n != nullNode) {

printInorder (n.getLeft ());

System.out.println (n.toString ());

printInorder (n.getRight ());

}

}

private voidprintLevelorder (Queue q) {

while (! q.isEmpty ()) {

TreeNode n = (TreeNode) q.leave ();

if (n.getLeft () != nullNode)

q.enter (n.getLeft ());

if (n.getRight () != nullNode)

q.enter (n.getRight ());

System.out.println (n.toString ());

}

}

...

// zur Zwischenspeicherung der Knoten ->1.4.2

Queue queue = new ArrayQueue ();

// Initialisierung

queue.enter (root);

// Aufruf

printLevelorder (queue);


1 8 5 weitere b ume

1.8.5Weitere Bäume

  • Für spezielle Anwendungen des Suchens und Sortierend werden bestimmte Spezialformen von Bäumen verwendet

    • Ausgeglichene (balanced) Bäume: Hier wird beim Auf- und Abbau des Baumes versucht ,die Tiefen der Teilbäume möglichst ähnlich oder sogar gleich zu halten:

      • AVL-Bäume sind binäre Bäume und beschränken die Niveaudifferenz aller Teilbäume auf 1.Sie werden vor allem zum Suchen verwendet .

      • B-Bäume (b steht für balanciert, buschig, breit) sind n-äre Bäume, bei denen alle Teilbäume gleichtief sind. Diese sind also meist nicht binär.Sie werden oft bei Datenbanksystemen zur Indexierung verwendet.

    • Digitale Bäume: Das sind n-äre Bäume die eine feste Anzahl von Verzweigungen (Nachfolgenknoten) unabhängig von den Werten im Baum haben.

      • Tries (retrieval): sind n-äre Bäume bei denen die n Werte (z.B. 127 ASCII-Werte) des Knotens als Index für die Nachfolgeknoten verwendet werden.Sie werden zum Suchen von Worten in Texten verwendet. (

      • Patricia-Bäume (Practical Algorithm to Retrieve Information Coded in Alphanumeric): Spezielle Form von Tries, bei denen Knoten mit nur einem Nachfolger übersprungen werden können.Auch Sie werden zum Suchen von Worten in Texten (oder von Gensequenzen in einem Genom) verwendet.

  •  Kapitel 2


1 9 graphen

1.9.Graphen

  • Graphen sind (oft) die komplexesten Grundstrukturen, mit denen man es bei abstrakten Datentypen zu tun hat.,,, und tatsächlich sind die im vorherigen Unterkapitel behandelten Bäume Spezialfälle von Graphen.

  • Arten

  • Umsetzung

  • Implementierung eines Graphen


1 9 1 arten

1.9.1Arten

  • Es gibt (neben anderen) drei wichtige Arten von Graphen

    • ungerichtete Graphen: Hier sind Knoten mit ungerichteten Kanten verbunden, d.h. es gibt kein Nachfolge- oder Vorgänger-Beziehung und auch kein Einschränkungen bezüglich Anzahl von Kanten pro Knoten.Anwendungen findet man bei der Modellierung von Straßenverbindungen (ohne Einbahnstraßen), der Nachbarschaft von Gegenständen oder eines Telefonnetzes.

    • gerichtete Graphen: Hier sind Knoten durch gerichtete Kanten verbunden, es kann also zwischen zwei Knoten bis zu zwei Kanten geben (eine hin, eine zurück).Anwendungen sind Modelle von Förderanlagen, der Kontrollfluss von Programmre

    • gerichtete azyklische Graphen (DAG directed acyclic graphs): dieser Spezialfall von gerichteten Graphen erlaubt keine Zyklen im Graph, d.h. es darf keinen Pfad von einem Knoten zu sich selbst geben.

      Zusätzlich können Kanten von Graphen noch gewichtet sein (gewichtete Graphen)

25

75

1

2

1

2

1

2

20

3

3

3

24

22

4

5

4

5

4

5

64

30

6

6

6


1 9 2 umsetzung

1.9.2Umsetzung

25

  • Die interne Darstellung von Graphen erfolgt (historisch) in vier Varianten:

    • Knotenliste:<#Knoten>,<#Kanten>, <Kanteniste> (<Kantenlliste> := <Vorgängerknoten>, <Nachfolgeknoten>)

      6, 8, 1,2, 1,4, 3,2, 3,5, 4,5, 4,6, 5,2, 6,3

    • Kantenliste:<#Knoten>,<#Kanten>, <Kantenliste> (<Kantenliste> := <#Nachfolgeknoten>,<Nachfolgeknoten, …>)

      6, 8, 2,2,4, 0, 2,2,5, 2,5,6, 1,2, 1,3

    • Adjazenzmatrix

      0 25 0 20 0 0 0 0 0 0 0 0 0 75 0 0 24 0 0 0 0 0 22 64 0 32 0 0 0 0 0 0 30 0 0 0

    • dynamische Adjazenzliste

75

1

2

20

32

3

24

22

4

5

64

30

6

1

2

3

4

5

6

3

2

2

5

2

5

6

4


1 9 3 implementierung eines graphen

1.9.3Implementierung eines Graphen

publicclass Graph {

staticclass Edge {

intdest, cost;

public Edge(int d, int c) {

dest = d; // Nachfolgeknoten

cost = c; // Gewicht

}

}

private ArrayList nodes;

public Graph() {

nodes = new ArrayList();

}

publicvoidaddNode(String label) { ... }

publicvoidaddEdge(String src, String dest, intcost) { ... }

publicIteratorgetEdges(intnode) { ... }

}


1 10 frameworks

1.10.Frameworks

  • Aufgrund des häufigen Einsatzes dieser ADTs gibt es praktisch für jede Programmiersprache entsprechende Bibliotheken.

  • ADTs in Programmiersprachen

  • Bibliotheken in Java


1 10 1 adts in programmiersprachen

1.10.1ADTs in Programmiersprachen

  • ADTs werden in vielen Programmiersprachen unterstützt:

    • Diese Bibliotheken sind zwar teilweise standardmäßig in den Entwicklungsumgebungen enthalten, sind aber (meist) nicht Teil des Sprachumfangs

    • Manche Programmiersprachen besitzen ADTs als Teil des Sprachumfangs.(z.B. good ol‘ Pascal: sets)

  • Beispiele für C++ und Java:

    • C++: Standard Template Library (Vorsicht: nicht standardisiert !)(z.B. http://www.sgi.com/tech/stl)

    • :Java Collection Framework (http://java.sun.com/docs/books/tutorial/collections/index.html)


1 10 2 bibliotheken in java

1.10.2Bibliotheken in Java

  • In Java sind diverse Klassen definiert, die die hier beschriebenen ADTs implementieren:

    • Vectorfunktioniert wie ein array, das bei Bedarf dynamisch wachsen kann.Nur für Integerwerte.Generische Variante: ArrayList

    • Stackferweiterert Vector zu eimem LIFO-Stack.

    • LinkedListDoppelt verkettete Liste, kann auch als Queue (Warteschlange) eingesetzt werden.

    • HashMapHashliste.TreeMap kann auch für gehashten (assoziativen) Zugriff verwendet werden, ist intern als Baum aufgebaut und etwas langsamer – dafür sind die Schlüssel alle sortiert.

    • TreeSetBalancierter Binärbaum. Die Elemente im Baum sind sortiert

  • Diese Klassen befinden sich im Paket: java.util.* und können mit import java.util.* eingebunden werden.


1 11 zusammenfassung

1.11Zusammenfassung

  • „Ein abstrakter Datentyp fasst die wesentlichen Eigenschaften und Operationen einer Datenstruktur zusammen, ohne auf deren eigentlichen Realisierung im Rechner einzugehen“

  • Stacks (Kellerspeicher, Stapel) sind einfache Abstraktionen von Strukturen, die in vielen Bereichen der Informatik, insbesondere aber in den systemnahen Bereichen verwendet werden.Stacks bezeichnet man manchmal auch als LIFO (Last in – First Out)-Schlangen

  • Queues (Warteschlangen) sind lineare Listen, deren Elemente nach dem FIFO-Prinzip (First in–First Out) ein- bzw. ausgefügt werden Auch Queues kommen in systemnahen Bereichen vor, insbesondere bei Betriebssystemen.

  • Listen sind (ziemlich) simple Datentypen, die sich statisch durch den konkreten strukturierten Datentyp „array (Feld)“ darstellen lässt und damit in den meisten Programmiersprachen implizit vorhanden ist.In der nicht-imperativen Programmiersprache LISP ist „Liste“ zudem der einzige strukturierte Datentyp.Möchte man die Länge einer Liste jedoch zur Laufzeit eines Programmes dynamisch verändern so muss man auf eigenen Umsetzungen mithilfe eines ADTs zurückgreifen.

  • Aus bestimmten Gründen – vor allem Laufzeit-Effizienz – verwendet man oft Listen, deren einzelne Elemente nicht nur den jeweiligen Nachfolger, sondern auch den jeweiligen Vorgänger kennen.Diese Listen nennt man das „Zweifach bzw. Doppelt verkettete Listen“

  • Bäume sind (zumindest) zweidimensionale Strukturen, die viele reale Strukturen abzubilden vermögen und zudem sehr gut zum Durchsuchen geeignet sind.Es gibt daher sehr viele spezielle Arten von Bäumen, von denen hier stellvertretend vor allem die binären Bäume behandelt werden sollen.

  • Graphen sind (oft) die komplexesten Grundstrukturen, mit denen man es bei abstrakten Datentypen zu tun hat (Tatsächlich sind die im vorherigen Unterkapitel behandelten Bäume Spezialfälle von Graphen)

  • Aufgrund des häufigen Einsatzes dieser ADTs gibt es praktisch für jede Programmiersprache entsprechende Bibliotheken.


  • Login