Die Präsentation wird geladen. Bitte warten

Die Präsentation wird geladen. Bitte warten

Einführung in die Programmierung Vorlesung SS 2006 Paul Manthey.

Ähnliche Präsentationen


Präsentation zum Thema: "Einführung in die Programmierung Vorlesung SS 2006 Paul Manthey."—  Präsentation transkript:

1 Einführung in die Programmierung Vorlesung SS 2006 Paul Manthey

2 Einführung in die Programmierung Motivation: Warum Programmierung? Notwendigkeit Ausgangspunkt „strukturiertes Denken“: systematische und strukturierte Analyse und Lösung von Aufgaben (abstrakt) Systementwicklung liefert formale Modelle für Anwendungssysteme, Abläufe, Steuerungen / Geräte,... Beschreibung und Programmierung von durch den Computer bearbeitbaren Aufgaben (real). Grenzen Nicht alles ist berechenbar: Ist eine Funktion f:  identisch 0, gilt also für alle reellen x: f(x) = 0? Nicht alles ist entscheidbar: Hält ein Java-Programm P mit der Eingabe D (Datei) irgendwann an oder läuft es unendlich weiter (Halteproblem)?

3 Einführung in die Programmierung Informaler Problembegriff Definition Unter einem Problem (Problemklasse) versteht man eine allgemeine Frage, die beantwortet werden soll. Gewöhnlich besitzt es Parameter (freie Variable), deren Werte zu spezifizieren sind. Ein Problem wird charakterisiert durch Eine allgemeine Beschreibung seiner Parameter. Eine Aussage darüber, welche Eigenschaften die Antwort oder Lösung des Problems erfüllen muss. Eine Probleminstanz erhält man als Spezialfall einer Problemklasse, wenn alle Parameter des Problems mit konkreten Werten spezifiziert werden. Der Unterschied zwischen einer Problemklasse und einer Probleminstanz liegt darin, dass Lösungen für eine Klasse immer die zugehörigen Instanzen lösen, aber nicht umgekehrt.

4 Einführung in die Programmierung Beispiel: Problem (1) Allgemeine Form Eingabe: Eine Liste von Parametern. Ausgabe: Antwort auf eine Fragestellung. Spezielle Form MULT Eingabe: a, b  Z Ausgabe: Welchen Wert hat das Produkt a · b? PRIM Eingabe: a  N Ausgabe: Ist a eine Primzahl?

5 Einführung in die Programmierung Beispiel: Problem (2) Optimale Teilung für 2 Teilnehmer Eingabe: Ein teilbares Objekt. Ausgabe: Wie teilt man so, dass alle Beteiligten zufrieden sind? Mögliche Eingabe-Parameter Anzahl der Beteiligten Konstanz der Anzahl Art des Objektes Beschaffenheit der Teile

6 Einführung in die Programmierung Datenmodell und Algorithmus Alle Problemlösungen haben Gemeinsamkeiten Sie beziehen alle Parameter des Problems in ihre Eingabe ein. Sie beschreiben Schritt für Schritt den Weg zur Lösung. Sie enden nach einer endlichen Anzahl von Schritten. Sie liefern die Lösung in einer dem Problem angemessenen Ausgabe. Definition Als Datenmodell bezeichnen wir die Gesamtheit aller Abstraktionen, die ein Problem beschreiben. Datenmodelle bilden die Grundlage für die Umsetzung eines Problems auf einen Computer. Die Zusammenfassung von Problemparametern und/oder Zwischenergebnissen beim Lösen des Problems nennen wir Datenstrukturen (Datentypen. Definition Als Algorithmus bezeichnen wir eine Technik, die mit endlich vielen Schritten oder Anweisungen Parameter einer Probleminstanz als Eingabegrößen in die gewünschten Ausgabegrößen transformiert.

7 Einführung in die Programmierung Historischer Überblick 300 v. Chr.: Euklids Algorithmus zur Bestimmung des ggT, (7. Buch der Elemente): ggT(300, 200) = n. Chr.: Muhammed ibn Musa abu Djafar alChoresmi: Aufgabensammlung für Kaufleute und Testamentsvollstrecker (lat.: Liber Algorithmi, Kunstwort aus dem Namen und griechisch „arithmos“ für Zahl) 1574: Adam Rieses Rechenbuch 1614: Napiers Logarithmentafeln (30 Jahre für Berechnung!) 1703: Binäres Zahlensysteme (Leibnitz) 1931: Gödels Unvollständigkeitssatz 1936: Church’sche These

8 Einführung in die Programmierung Eigenschaften von Algorithmen (1) Korrektheit Wir setzen voraus, dass mit einem Algorithmus das gestellte Problem richtig gelöst werden kann. Meist ist dies offensichtlich der Fall, manchmal muss jedoch ein formaler Beweis die Tauglichkeit zeigen. Der Nachweis durch Test einiger Lösungen für Probleminstanzen ist nicht ausreichend, da damit – wie Dijkstra einst bemerkte – nur „die Anwesenheit, aber nicht die Abwesenheit von Fehlern“ gezeigt werden kann. Terminierung Ein Algorithmus muss nach einer endlichen Anzahl von Schritten abbrechen. Tut er das nicht, werden wir ihn als Berechnungsmethode oder Prozess bezeichnen. Prozesse treten vor allem dort auf, wo Algorithmen mit ihrer Umgebung interagieren (z.B. bei Betriebssystemen, Shells).

9 Einführung in die Programmierung Eigenschaften von Algorithmen (2) Determinismus Jeder Schritt des Algorithmus muss so genau bestimmt sein, dass er zu einem unzweideutigen – nicht zufälligen – Ergebnis führt. Das bedeutet in der Praxis, dass bei gegebener, gleicher Problemklasse für unterschiedliche Probleminstanzen die Eingabegrößen gleichartig in Ausgabegrößen transformiert werden. Offenbar hängt diese Eigenschaft stark davon ab, in welcher Form der Algorithmus dargestellt wird. Effizienz Die Güte eines Algorithmus ist nicht einfach zu bestimmen. Soll der Algorithmus auf einen Computer „leicht“ umsetzbar sein und darf er nur eingeschränkt Ressourcen benutzen – wie z.B. Zeit, Speicherplatz, CPU oder Papier? Sind nur bestimmte Schritte im Algorithmus zugelassen bzw. kann er auf bestehende Algorithmen aufbauen? Soll der Algorithmus ein bestimmtes Paradigma unterstützen, z.B. Objektorientierung oder modulare Programmiertechniken?

10 Einführung in die Programmierung Algorithmisierbare Prozesse Kochrezepte Pizza aufwärmen Seeteufel mit Kräuterkruste auf Lauch Bedienungsanleitungen Suchen eines Telefonbucheintrags Herausgeben von Wechselgeld Sortieren von Spielkarten Berechnungsvorschriften schriftliches Addieren Berechnung der Fakultät (x! = x · (x − 1) · · · · · 3 · 2 · 1) Berechnung des größten gemeinsamen Teilers ggT zweier Zahlen

11 Einführung in die Programmierung Darstellungsformen von Algorithmen (1) Umgangssprache Meist unvollständig Nicht immer ausreichend exakt, um eine spätere Transformation des Algorithmus auf einen Computer durchzuführen Beispiel 1: Koche Wasser. Gib Kaffeepulver in Tasse. Fülle Wasser in Tasse. Beispiel 2: S1: Gib Kaffeepulver in Tasse. S2: Koche Wasser. S3: Fülle Wasser in Tasse.

12 Einführung in die Programmierung Darstellungsformen von Algorithmen (2) Diagrammformen Flussdiagramm (englisch Flowchart) ist die grafische Darstellung der Ablaufstruktur eines Algorithmus, die die Aufeinanderfolge von Schritten sichtbar macht. Spezielle Flussdiagramme der Informatik sind Datenflussplan und Ablaufplan. Struktogramm (Nassi-Shneiderman-Diagramm) benutzt als Grund- element den als Rechteck dargestellte Strukturblock mit einer Eingangs- und einer Ausgangskante, der für einen Algorithmusschritt steht und in dem diese Funktion benannt oder beschrieben wird.

13 Einführung in die Programmierung Kontrollstrukturen in Algorithmen Sequenz Besteht aus Schritten bzw. Anweisungen, die als zusammengesetzter Strukturblock oder eben als Sequenz bezeichnet werden. Auswahl (Verzweigung) Wird innerhalb eines Algorithmus eingesetzt, wenn eine oder mehrere Folgeanweisungen nur unter einer bestimmten Bedingung auszuführen sind. Existiert als einfache, zweifache und CASE-Verzweigung Wiederholung (Schleife) Steuert die Wiederholungen einer oder einer Folge von Anweisungen unter Beachtung eines bestimmten Zustandes Existiert als kopf- bzw. fußgesteuerte WHILE- bzw. REPEAT-Schleife Subalgorithmus (Prozedur) Als eigenständiger Algorithmus implementierte Prozedur oder Funktion, die von einem Hauptalgorithmus aus aufgerufen wird.

14 Einführung in die Programmierung Diagrammdarstellungen (1) Sequenz

15 Einführung in die Programmierung Diagrammdarstellungen (2) Auswahl (Verzweigung)

16 Einführung in die Programmierung Diagrammdarstellungen (3) Wiederholung (Schleife)

17 Einführung in die Programmierung Diagrammdarstellungen (4) Subalgorithmus (Prozedur)

18 Einführung in die Programmierung Darstellungsformen von Algorithmen (3) Pseudocode Semi-formale Sprache Beschreibt Ablaufstrukturen eines Algorithmus grob durch Texte und fest vorgegebene Schlüsselwörter Beispiel procedure Euklid (m, n) loop r = m mod n m = n n = r until r = 0 return m end procedure

19 Einführung in die Programmierung Effizienz Neben den bisher vorgestellten, formalen Eigenschaften interessieren vor allem eine Frage: Die Effizienz, d.h. Leistungsfähigkeit bei der Ausführung, z.B. zum Vergleich verschiedener vorhandener Algorithmen. Frage Wie misst man die Effizienz eines Algorithmus? Üblicherweise durch die von dem Algorithmus für die Lösung des Problems benötigten Ressourcen: Den benötigten Platz und Die benötigte Zeit. Definition Unter der Speicherkomplexität eines Algorithmus versteht man die Messung des zu seiner Ausführung nötigen Speicherplatzes, unter Zeitkomplexität analog die nötige Laufzeit. Frage Wie misst man die benötigte Zeit und den benötigten Platz?

20 Einführung in die Programmierung Die Random Access Maschine Zur Präzisierung der Begriffe Rechenzeit und Speicherbedarf benötigt man ein präzises (idealisiertes) Rechnermodell. Definition Eine Random-Access-Maschine (RAM) (mit k Registern) besteht aus k Registern  0,...,  k. Einer unendlichen Zahl von Speicherzellen R i, i ∈ N. Einem Programm P, bestehend aus Befehlen P 0,..., P l. Einem Befehlszähler . Jedes Register und jede Speicherzelle enthält eine natürliche Zahl. Die Inhalte werden mit  X  bezeichnet.

21 Einführung in die Programmierung Funktionsweise der RAM In jedem Schritt tut die RAM folgendes: 1.Lese den Inhalt i von . 2.Erhöhe  um eins. 3.Lade Befehl P i. 4.Führe den Befehl aus. Bei der Ausführung des Befehls werden unter Umständen die Inhalte der Register, der Speicherzellen und des Befehlszählers geändert - nicht jedoch das Programm.

22 Einführung in die Programmierung Befehlssatz der RAM: Transportbefehle

23 Einführung in die Programmierung Befehlssatz der RAM: Sprungbefehle

24 Einführung in die Programmierung Befehlssatz der RAM: Arithmetische und Indexbefehle

25 Einführung in die Programmierung Beispiel: Berechnung von 2 n mit 2 Registern

26 Einführung in die Programmierung Nachteile des RAM-Modells Die RAM ist natürlich in folgenden Hinsichten unrealistisch: Es stehen unendlich viele Speicherzellen zur Verfügung Jedes Register und jede Speicherzelle (und jeder Befehl) kann eine beliebige natürliche Zahl speichern (d.h. bereits unendlicher Speicher pro Zelle) Dennoch spiegelt das Modell sehr gut die Eigenschaften eines „natür- lichen“ Computers wider. Um die Effizienz von Algorithmen auf diesem Rechnermodell messen zu können, benötigen wir ein Kostenmodell. Im Folgenden führen wir zwei gebräuchliche Kostenmaße ein und anschließend ein Konzept zur Laufzeitbetrachtung, das uns ermöglicht, das Verhalten von Algorithmen zu bewerten.

27 Einführung in die Programmierung RAM: Kostenmaße (1) Einheitskostenmaß (uniforme Kosten) Jeder Speicherzugriff kostet eine Einheit. Jede Ausführung eines Kernbefehls kostet eine Einheit. Dieses Maß ist realistisch, wenn die vorkommenden Parameter jeweils in eine Speicherzelle eines realen Computer passen (Wortgröße) Logarithmisches Kostenmaß Jeder Kernbefehl kostet eine Einheit. Die Kosten für alle anderen Argumente sind proportional zur Länge der Binärdarstellung der Zahlen, d.h.

28 Einführung in die Programmierung RAM: Kostenmaße (2)

29 Einführung in die Programmierung Verhalten im schlechtesten Fall Um einen Algorithmus A möglichst detailliert bewerten zu können, könnte man einfach für jede mögliche Eingabe x die Zeit T A (x) messen, die A be- nötigt, um das Problem zu lösen. Dies ist im Allgemeinen jedoch nicht praktikabel. Daher beschränkt man sich üblicherweise auf das Verhalten im schlechtesten Fall. Dazu weist man jeder Eingabe x eine Größe |x|  N zu, und betrachtet die maximale Zeit, die der Algorithmus zum Lösen des Problems auf allen Eingaben derselben Größe benötigt. Definition (Worst-Case-Laufzeit) T A (n) := sup {T A (x) | x  PROBLEM, |x| = n}

30 Einführung in die Programmierung Verhalten im Mittel In vielen Fällen stellt das Verhalten im schlechtesten Fall nur ein ungenaues Maß dar. So kann z.B. die Lösung eines bestimmten Falles sehr lange brauchen, während alle anderen Fälle in sehr viel kürzerer Zeit gelöst werden können. In solchen Fällen kann man das Verhalten im Mittel betrachten. Dazu nimmt man an, dass die Eingabe x mit einer gewissen Wahrschein-lichkeit 0 < p(x) < 1 auftritt. Definition (Expected-Time-Laufzeit) T A avg (n) := E( {T A (x) | x  PROBLEM, |x| = n}) =  p(x) * T A (x) x  PROBLEM |x| = n

31 Einführung in die Programmierung Komplexitätsanalyse und Big-O-Notation Definition (Big-O-asymptotisch) Die Funktion f(n) ist von der Größenordnung der Funktion g(n) bzw. f(n) ist O(g(n)) oder f(n) ist in O(g(n)), geschrieben f(n) = O(g(n), falls Kon- stante c 1, c 2 und n 0 existieren, so dass gilt f(n)  c 1  g(n) + c 2  n  n 0. Um auszudrücken, dass eine Größenordnung die kleinstmögliche ist, kann die in der Literatur bekannte  -Notation verwendet werden Definition Es gilt f(n) =  (g(n)), falls f(n) = O(g(n)) ist und Konstante c 1, c 2 und n 0 existieren, so dass gilt f(n)  c 1  g(n) + c 2  n  n 0, d.h. f(n) und g(n) unterscheiden sich f ü r gro ß es n nur um eine Konstante.

32 Einführung in die Programmierung Komplexität von Problemen: Obere Schranken Definition Ein Problem PROB hat die Zeitkomplexität O(f ) für f : N  N, wenn es einen Algorithmus A für PROB gibt mit T A (n)  O(f ). Eine solche obere Schranke für die Zeitkomplexität eines Problems kann somit durch die Analyse eines Algorithmus erreicht werden. Häufig ergeben sich recht einfache obere Schranken, die aber sehr ungenau sind.

33 Einführung in die Programmierung Beispiel: Kosten für die Berechnung von 2 n (1)

34 Einführung in die Programmierung Beispiel: Kosten für die Berechnung von 2 n (2)

35 Einführung in die Programmierung Beispiel: Kosten für die Berechnung von 2 n (3)

36 Einführung in die Programmierung Beispiel: Kosten für die Berechnung von 2 n (4)

37 Einführung in die Programmierung Vergleichswerte von Größenordnungen

38 Einführung in die Programmierung Darstellungsformen von Algorithmen (4) Definition Ein Programm ist ein in einer Programmiersprache formulierter Algorithmus Definition Eine Programmiersprache besteht aus einem Alphabet von Zeichen, wobei die Wörter einer Sprache durch (formale) Regeln - die Grammatik - gebildet werden. Die Grammatik einer Programmiersprachen heisst Syntax, ihre inhaltliche Bedeutung Semantik. Syntax: Formale Regeln, welche Sätze gebildet werden können: „Der Elefant aß die Erdnuss.“ (syntaktisch korrekt) „Der Elefant aß Erdnuss die.“ (syntaktisch falsch) Semantik: (Formale) Regeln, welche Sätze eine Bedeutung haben: „Der Elefant aß die Erdnuss.“ (semantisch korrekt, „sinnhaft“) „Die Erdnuss aß den Elefanten.“ (semantisch falsch, „sinnlos“)

39 Einführung in die Programmierung Beispiel: Java einfach automatisierte Speicherverwaltung Verzicht auf Zeiger und goto objektorientiert robust und sicher starke Typisierung Laufzeitüberprüfung von Zugriffen interpretiert und dynamisch virtuelle Java-Maschine „kleine“ Programme architekturneutral und portabel plattformunabhängiger Zwischencode (Bytecode) Programme sind ohne Änderungen ablauffähig unter Windows, Unix, MacOS,...

40 Einführung in die Programmierung Systemprogramme zur Programmierung (1) Compiler Programme werden als Quelltext formuliert und durch einen Compiler in eine, dem Computer verständliche (Maschinen-)Sprache übersetzt. Aufgaben des Compilers Zeichenweises Einlesen des als Text formulierten Programms Erkennung von Grundsymbolen. Diese sind: Operatoren wie z.B. =, +, -, /, &... Trennzeichen wie z.B. ( ) { }, : ; [ ]... Schlüsselworte wie if, then, else, while,... Konstanten wie 1, -5, +1.5, - 3e10... Bezeichner, das sind Namen für Programmobjekte, die der Programmierer selbst vergeben kann wie z.B. Variablennamen Prüfen auf syntaktische Korrektheit Übersetzen des Textes in die Maschinensprache

41 Einführung in die Programmierung Systemprogramme zur Programmierung (2) Linker (Binder) und Loader (Lader) Ein Programm benutzt i.a. mehrere Programmobjekte, die zu einem Programm zusammengesetzt werden, z.B. Programmstücke, mit denen man Daten einlesen und ausgeben kann Zugriff auf Eingabegeräte Funktionen des Betriebssystems Aufgabe des Linkers übersetzte Module zu einem lauffähigen Programm zusammenfügen Informationen zur Speicherverwaltung eintragen Das Programm in einer Datei auf Festplatte speichern (executable). Aufgabe des Laders das in Maschinensprache übersetzte Programm von der Programmdatei in den Arbeitsspeicher laden und von der CPU ausführen lassen.

42 Einführung in die Programmierung Systemprogramme zur Programmierung (3) Interpreter Interpreter übersetzen Programme zeilenweise im Quelltext. Jede Zeile wird sofort in Maschinensprache übertragen und ausgeführt. Fehler im Programmfluss können sofort während der Übersetzung erkannt werden. Nachteil Die Programmabarbeitung wird deutlich langsamer, da nach jeder Ausführung von Maschinenanweisungen erst wieder der Interpreter die nächste Zeile bearbeitet. Jeder neue Programmlauf wird wieder neu übersetzt. Computerressourcen werden mehrfach benutzt

43 Einführung in die Programmierung Java-Werkzeuge (1) Java-Compiler javac überprüft Quelltext auf Fehler übersetzt Quelltext in plattformneutralen Zwischencode (Bytecode) Java-Interpreter java interpretiert Bytecode implementiert virtuelle Java-Maschine

44 Einführung in die Programmierung Java-Werkzeuge (2)

45 Einführung in die Programmierung Paradigma 1 : Strukturierte Programmierung liegt der klassischen, prozeduralen Programmierung zugrunde. Arbeitet mit Kontrollstrukturen Programmiersprachen: Fortran, Basic, Pascal, C. Computer = Maschine zur Veränderung von Variablenwerten. Programm = Plan für den Berechnungsprozess mit Angabe der Befehle Programmfindung: Elementare Einzelschritte finden und in flexible Reihenfolge bringen.

46 Einführung in die Programmierung Paradigma 2 : Objektorientierte Programmierung Baut auf der strukturierten Programmierung auf Verfolgt einen ganzheitlichen Ansatz, in dem Daten und Programmcode miteinander verbunden sind. Programmiersprachen: Simula, C++, Smalltalk, Delphi, Java,... Computer = Umgebung für virtuelle Objekte Programm = Auflistung von (Objekt-) Klassen, d.h. allgemeiner Spezifikationen von Objekten, die zur Laufzeit des Programms (mehrfach) kreiert und wieder vernichtet werden können und miteinander kommunizieren. Programmfindung: Spezifikation der Klassen (Daten und Methoden), die Objektstruktur und -verhalten festlegen.

47 Einführung in die Programmierung Konzepte der Objektorientierung Definition Als Objekt bezeichnet man in der objektorientierten Programmierung (engl.: object-oriented programming; OOP) die Instanz einer Klasse. Das Objekt enthält Daten, die Klasse enthält die Funktionen (Methoden) zu deren Verarbeitung. Das Objekt wird als eine Einheit (Entität) behandelt. Ein Objekt existiert nur für die Dauer der Laufzeit des entsprechenden Programms. Ist das Programm abgelaufen, beendet das Objekt seine Existenz. Haupteigenschaften von Objekten Kapselung: Verbergen der Implementierungsdetails eines Objekts. Vererbung: Fähigkeit, bestehende Objekte bei der Erstellung neuer, stärker spezialisierter Objekte wiederzuverwenden. Polymorphie: Fähigkeit des Codes, abhängig vom verwendeten Objekt unterschiedliche Verhaltensweisen zu zeigen.

48 Einführung in die Programmierung Struktur eines Java-Programms

49 Einführung in die Programmierung Kapselung Definition Kapselung bedeutet das Verbergen der Details eines Objekts vor anderen Teilen des Programms. Das Objekt kann nur über seine Zugriffsmethoden verwendet werden, die das Objekt konsistent und geschützt halten. Kapselung lässt ein Objekt wie eine Blackbox aussehen: Das Innere einer Box ist vor Blicken geschützt. Von außen gibt es einige Steuerelemente, die für den Anwender die einzige Möglichkeit darstellen, die Box zu verwenden. Beispiel Ein Fernsehgerät versperrt dem Benutzer den Zugang zu den meisten inneren Abläufen. Der Benutzer kommuniziert mit dem Gerät über wohl definierte Steuerelemente. Die Steuerelemente werden auch als Interface bezeichnet.

50 Einführung in die Programmierung Vererbung Definition In der objektorientierten Softwareentwicklung können Klassen Eigenschaften von anderen Klassen erben. Wenn eine Klasse von einer Basisklasse geerbt hat, spricht man davon, dass sie von der Basisklasse abgeleitet ist. Abgeleitete Klassen besitzen alle Operationen und Attribute der Basisklasse, können aber auch zusätzliche Eigenschaften haben. Fazit Vererbung bedeutet Spezialisierung Abgeleitete Klassen können Operationen von Basisklassen überschreiben. Klassen können nur von einer Basisklasse abgeleitet werden (Java) oder auch von mehreren (C++). Mehrfachvererbung bedeutet, dass eine Klasse von mehreren Basisklassen abgeleitet sein kann.

51 Einführung in die Programmierung Polymorphie Definition Polymorphie („Vielgestaltigkeit“) bedeutet, dass Funktionen bzw. Methoden einem bestimmten Typ bzw. einer bestimmten Klasse zugeordnet sind, und je nach Typ/Klasse eines bestimmten Objekts die zugehörige Funktion/Methode ausgeführt wird. Beispiel In einem Zeichenprogramm existieren geometrische Primitive wie Linie, Ellipse, Rechteck usw. Falls alle von einer Basisklasse eine Methode zeichnen ableiten sollen, wird jede Klasse die ihr gemäße Zeichenoperation überschreiben, um gerade oder runde Linien zu erzeugen. Trotzdem kann der Name zeichnen weiterhin von allen gemeinsam verwendet werden.

52 Einführung in die Programmierung Ein erstes Java-Programm /* Hello.java - Das erste Java Programm. */ // Jedes Java-Programm besteht aus mind. einer Klasse. public class Hello { // Eine Standalone-Anwendung muss eine main-Methode besitzen public static void main(String[] args) { // Zeichenkette ausgeben System.out.println("Hello Java !"); }

53 Einführung in die Programmierung Übersetzung und Ausführung 1.Quelltext in Datei Hello.java speichern Dateiname entspricht Klassennamen! Klasse muss eine Methode main als Startpunkt der Ausführung besitzen 2.Quelltext kompilieren: Quelltext in Bytecode übersetzen liefert Datei Hello.class mit prompt> javac Hello.java 3.Java-Programm ausführen Interpretieren des Bytecodes mit prompt :\> java Hello 4.Ergebnis prompt :\>Hello Java !

54 Einführung in die Programmierung Datentypen und Datenstrukturen Definition Ein Datentyp (kurz Typ) besteht aus einer Objektmenge (auch Wertebereich genannt) und darauf definierten Operationen. In der Programmierpraxis handelt es sich dabei um eine Festlegung, wie ein Speicherbereich von einem Computer interpretiert werden soll. Verschiedene Programmiersprachen und Plattformen unterscheiden sich sehr stark darin, welche Datentypen sie anbieten. Daher wird meist nur ein Teil der nachfolgend genannten Datentypen zur Verfügung stehen, gelegentlich auch weitere oder andere. Man unterscheidet zwischen elementaren und strukturierten Datentypen.

55 Einführung in die Programmierung Elementare Datentypen Ordinale (aufzählbare) Datentypen Boolean (Wahrheitswert, der genau die beiden Werte false und true annehmen kann) Ganze Zahlen (Integer, Long, Natural,...) Elemente des Zeichensatzes (Char) Aufzählungstypen, z. B.: type Kartenfarbe = (Kreuz, Pik, Herz, Karo) Teilbereichstypen, z. B.: type zweiundvierzig = Realtypen Festkomma- oder Gleitkommazahlen (Float, Real, Double,...) Zeichenketten (Strings) Strukturierte Datentypen Zeiger (Pointer) Objekttypen (siehe Objektorientierte Programmierung)

56 Einführung in die Programmierung Datentyp: bool boolean, auch bool: Datentyp der Wahrheitwerte Werte: {true, false} Operationen: , auch not: logische Negation , auch and: logisches Und , auch or: logisches Oder  : Implikation Operationen definiert durch Wahrheitstafeln: p  q ist definiert als  p  q

57 Einführung in die Programmierung Datentyp: integer integer, auch int: Datentyp der ganzen Zahlen Werte: {...,−2,−1, 0, 1, 2, 3, 4,... } Operationen +,−, ·,÷, mod, sign, >, <,.... +: int × int  int Addition,  7 mod: int × int  int Rest bei Division, 19 mod 7  5 sign: int  {−1, 0, 1} Vorzeichen, sign(7)  1, sign(0)  0, sign(−7)  −1, >: int × int  bool Größerrelation: 4 > 3  true weiter übliche Operationen, insbesondere in folgenden Beispielen abs zur Berechnung des Absolutbetrags, odd und even

58 Einführung in die Programmierung Zeichenketten char: Zeichen in Texten {A,.., Z, a,..} mit Operation = string: Zeichenketten über char Gleichheit = Konkatenation („Aneinanderhängen“): + Selektion des i-ten Zeichens: s[i] Länge: length jeder Wert aus char wird als ein string der Länge 1 aufgefasst, wenn er wie folgt notiert wird: ’A’ empty als leerer string weitere sinnvolle Operatoren, etwa substring()

59 Einführung in die Programmierung Felder array: „Felder“ mit Werten eines Datentyps als Eintrag, Ausdehnung (Speicherplatz pro Eintrag) fest vorgegeben Definition: array 1..3 of int; array 1..3, 1..3 of int; Operationen: Gleichheit = Selektion eines Elements: A[n] oder A[1, 2] Konstruktion eines Feldes: (1, 2, 3) oder ((1, 2, 3), (3, 4, 5), (6, 7, 8))

60 Einführung in die Programmierung Datentypen in Java definieren Struktur, Wertebereich und zulässige Operationen für Datenstrukturen strenge Typisierung: jede Variable hat einen wohldefinierten Typ Typumwandlung nur unter bestimmten Bedingungen zulässig Unterscheidung in primitive Datentypen Referenzdatentypen

61 Einführung in die Programmierung Primitive Datentypen „eingebaute“ Datentypen Speicherung von Werten statisch, nicht erweiterbar Arten numerisch (Ganzzahl, Gleitkommazahl) Zeichen-Datentypen Boolesche Datentypen

62 Einführung in die Programmierung Numerische Datentypen ganzzahlige Werte: byte, short, int, long Gleitkomma-Werte: float, double

63 Einführung in die Programmierung Zeichen-Datentypen char: vorzeichenloser 16-Bit-Integer-Typ Repräsentation von Zeichen im Unicode-Zeichensatz Wertebereich: ´\u0000´ bis ´\uffff´ Repräsentation von Zeichenketten (Strings) durch eine Klasse java.lang.String (Achtung: Großschreibung!!!)

64 Einführung in die Programmierung Boolscher Datentypen boolean: 1 Bit-Werte Repräsentation von Wahrheitswerten mögliche Werte: false und true Ergebnistyp für logische Vergleiche Konvertierung zwischen integer-Werten und boolean-Werten ist nicht zulässig!

65 Einführung in die Programmierung Bezeichner und Literale Bezeichner Namen für Variablen, Klassen, Attribute, Methoden usw. beliebige Länge, keine Schlüsselworte alle ASCII-Zeichen, _, $ Nomenklatur (Namensvereinbarung) empfohlen Literale (Konstante) numerische Werte: 42, 345.4, 7.899E+34 Zeichen: ´a´, ´\u0012´ Zeichenketten: "Ein String"

66 Einführung in die Programmierung Variablen benannter Speicherbereich (primitiver Datentyp) bzw. benannter Verweis (Referenz-Datentyp) auf Speicherbereich, in dem Wert abgelegt werden kann besitzt Typ: Wert und Operationen müssen Typ entsprechen muss vor Verwendung deklariert werden Festlegung des Typs, Initialisierung bestimmte Sichtbarkeit

67 Einführung in die Programmierung Variablendeklaration Notation typ bezeichner [ = init_wert ]; Vereinbarung überall in Methoden oder Anweisungsblöcken vorzugsweise zu Beginn eines Blocks Beispiele int eineVariable = 23; float a, b; char c1 = ’A’, c2 = ’B’; boolean aBoolValue = true;

68 Einführung in die Programmierung Referenzdatentyp Variablen dieser Typen enthalten nicht Daten selbst, sondern Verweis (Referenz) auf Speicherort der Daten Standardwert: null Vergleich (==) und Zuweisung (=) erfolgt auf Referenzen!! Referenzdatentypen: Arten Feld (Array): Datenstruktur fester Größe, die aus Elementen gleichen Typs (sowohl primitive als auch Referenzdatentypen) aufgebaut ist Objektdatentyp: Repräsentation von Referenzen auf Objekte

69 Einführung in die Programmierung Felder Felder = Referenzdatentypen (Verweis) int einFeld[]; int[] auchEinFeld; erfordert explizite Allokation new-Operator zur Bereitstellung des Speicherplatzes direkte Instantiierung mit Literalen Zuweisung einer anderen Feld-Referenz

70 Einführung in die Programmierung Felder: Allokierung und Zugriff Allokierung new-Operator int[] feld = new int [20]; Initialisierung mit Literalen int[] feld = { 5, 23, 42 }; Zuweisung int[] nochEinFeld = feld; Zugriff auf i-tes Element mit feld[i] mit i = 0... feld.length−1

71 Einführung in die Programmierung Operatoren (1) Unäre Operatoren ++ (Inkrement) -- (Dekrement) ! (Komplement) Bsp.: a++ (entspricht a = a+1) --b !true Arithmetische Operatoren + - * / % (Rest bei Division) Bsp.: 45 * c / (d - 34) Vergleichsoperatoren = == (Gleichheit) != (Ungleichheit) Bsp.: 34 >= cx == y Logische Vergleichsoperatoren && (UND) || (ODER) Bsp.: a > b && c == true

72 Einführung in die Programmierung Operatoren (2) Zuweisungsoperatoren = (Zuweisung) += -= *= /=... Bsp.: a = 34b += 1 (entspricht b = b + 1) Verschiebeoperatoren (Bitweises Verschieben) > (nach rechts) Bitoperatoren bitweises & (UND) | (ODER)

73 Einführung in die Programmierung Ausdrücke Wertzuweisungen, Berechnungen Primäre Ausdrücke Namen, Konstanten: xeineVariable42 Feldzugriffe: feld[23] Methodenaufrufe: obj.methode() Allokationen (Erzeugen von Objekten) new int[5] new Vector() Zusammengesetzte Ausdrücke durch Verwendung von Operatoren

74 Einführung in die Programmierung Anweisungen Arbeitsschritt eines Programms durch „;“ abgeschlossen Arten leere Anweisung Ausdrücke Bedingungen, Schleifen, Sprünge... Zusammenfassung mehrerer Anweisungen zu einem Block durch Klammerung { anw1; anw2;...anw3; }

75 Einführung in die Programmierung Kontrollstrukturen Bedingungs- und Auswahlanweisungen if-else switch Schleifenanweisungen while, do-while for Sprunganweisungen break, continue, return

76 Einführung in die Programmierung if else Anweisung Syntax if ( bedingung ) anw1; [ else anw2; ] Anweisung bzw. Anweisungsblock anw1 wird nur ausgeführt, wenn Bedingungsausdruck bedingung erfüllt ist (true liefert), andernfalls anw2. Beispiele if (x == 0) y = 3; else y = -3; if (x > y) { m = x; n = 2 * y; }

77 Einführung in die Programmierung switch Anweisung (1) Syntax switch ( ausdruck ) { case auswahlwert1: // Anweisungen für Fall #1 [ break; ] case auswahlwert2: // Anweisungen für Fall #2 [ break; ] default: // Anweisungen für alle anderen Fälle [ break; ] }

78 Einführung in die Programmierung switch Anweisung (2) verallgemeinerte Form der Fallunterscheidung für jeden Wert des Ausdrucks ausdruck eigene Anweisungsfolge Ausdruck muss ganzzahligen Wert liefern: char, byte, short, int Auswahlwerte: Literale ohne break: Kontrollfluss zu nächster Anweisung default-Zweig ist optional

79 Einführung in die Programmierung Beispiel: switch Anweisung int i =...; switch (i) { case 0: System.out.println("Null"); break; case 1: case 2: System.out.println("eins oder zwei"); break; default: System.out.println("größer als zwei"); break; }

80 Einführung in die Programmierung while Schleife Bedingte Schleife mit Bedingungsprüfung am Anfang Syntax while ( bedingung ) anweisung; Solange der Ausdruck bedingung erfüllt ist (true), wird die Anweisung bzw. der Anweisungsblock anweisung ausgeführt Überprüfung der Bedingung vor jedem Durchlauf d.h. wenn die Bedingung nicht erfüllt ist, wird anweisung nicht ausgeführt

81 Einführung in die Programmierung Beispiel: while Schleife Zählschleife: int i = 5; while (i > 0) { System.out.println(i); i--; } Endlosschleife while (true) System.out.println("Endlos..."); Leere Schleife while (true) ;

82 Einführung in die Programmierung do while Schleife Bedingte Schleife mit Bedingungsprüfung am Ende des Durchlaufs Syntax do anweisung; while ( bedingung ); Anweisung bzw. Anweisungsblock anweisung wird ausgeführt, solange der Ausdruck bedingung erfüllt ist (true) Überprüfung der Bedingung nach jedem Durchlauf d.h. Schleifenrumpf wird mindestens einmal ausgeführt

83 Einführung in die Programmierung Beispiel: do while Schleife Zählschleife: int i = 1; do { System.out.println(i); i++; } while (i <= 5); Endlosschleife do System.out.println("Endlos"); while (true);

84 Einführung in die Programmierung for Schleife Syntax for ( init_ausdr ; bed_ausdr ; mod_ausdr ) anweisung; Initialisierungsausdruck init_ausdr: Zählvariable auf Startwert setzen (und evtl. deklarieren) Bedingungsausdruck bed_ausdr: Bedingung für Fortsetzung (Ausführung des Schleifenrumpfes) Modifikationsausdruck mod_ausdr: Verändern der Zählvariablen Semantik 1.Zählvariable deklarieren und initialisieren 2.Solange Bedingungsausdruck erfüllt ist (true liefert) 3.Führe Anweisung bzw. Anweisungsblock anweisung aus 4.Berechne Modifikationsausdruck (Verändern der Zählvariablen)

85 Einführung in die Programmierung Beispiel: for Schleife Zählschleife for (int i = 0; i < 5; i++) System.out.println(i); Endlosschleife for (;;) System.out.println("Endlos"); Weitere Möglichkeiten int i = 0, n = 0; for (; i < 5 && n < 10; i++, n += 3) { //... }

86 Einführung in die Programmierung return Anweisung Beenden der Methodenausführung Rücksprung zur Aufrufstelle Rückgabe eines Wertes (Ergebnis) Syntax return [ ausdruck ]; Beispiel int plus(int a, int b) { return a + b; }

87 Einführung in die Programmierung break Anweisung Unterbrechen des Kontrollflusses des aktuellen Blocks Fortsetzung nach Anweisungsblock Beispiel int i = 0; while (true) { if (i == 10) break; //... }

88 Einführung in die Programmierung continue Anweisung Unterbrechen des Kontrollflusses des aktuellen Blocks Fortsetzung der Schleife mit der nächsten Iteration Beispiel for (int i = 0; i < 10; i++) { if (i % 2 == 0) continue; System.out.println(i); }

89 Einführung in die Programmierung Methoden Logische Einheit von einer oder mehreren Anweisungen Immer im Kontext (Scope) einer Klasse definiert! Definieren das Verhalten von Objekten Bilden die Schnittstelle (Interface) eines Objektes nach außen Entsprechen Funktionen oder Prozeduren Können mit Parametern aufgerufen werden Können Ergebnis (z.B. einer Berechnung) liefern Spezielle Methode: main  Hauptprogramm public static void main(String[] args) { Anweisungsfolge } Spezielle Methoden: Konstruktor und Destruktor

90 Einführung in die Programmierung Methodendefinition Notation sichtbarkeit [ static ] datentyp name (parameterliste) { anweisungen } Sichtbarkeit: public (öffentlich), protected, private (nichtöffentlich) static Klassenmethode (nicht auf Objekt-Instanz angewiesen!) Datentyp des Rückgabewertes oder void (keine Rückgabe) Parameterliste typ1 name1,..., typN nameN Methodensignatur datentyp name (parameterliste)

91 Einführung in die Programmierung Beispiel: Fakultät (rekursiv) import algoj.IOUtils; public class FacRecursive { public static int factorial(int x) { if (x <= 1) return 1; else return x * factorial(x - 1); } public static void main(String[] args) { int z; System.out.print("Zahl: "); z = IOUtils.readInt(); System.out.println("Fakultät(" + z + ") = " + factorial(z)); }

92 Einführung in die Programmierung Beispiel: Fakultät (imperativ) import algoj.IOUtils; public class FacImperative { public static int factorial(int x) { int y = 1; while (x > 1) { y = y * x; x--; } return y; } public static void main(String[] args) { int z;... }

93 Einführung in die Programmierung Datenstrukturen Arrays (auch Felder, Elemente gleichen Datentyps) eindimensional (Vektoren) zweidimensional (Tabellen) mehrdimensional Kellerspeicher (auch Keller, Stapel, Stack) Listen, meist verkettet Bäume Binärbaum AVL-Baum B-Baum...

94 Einführung in die Programmierung Array Definition Ein Array (Feld, Reihung, Vektor) ist eine Datenstruktur, die eine Sequenz von Datenwerten (elementare Datentypen) oder Objektreferenzen speichert und einen schnellen Zugriff auf beliebige Werte der Sequenz über einen Index gestattet. Vorteile Schneller Zugriff (Random Access ist in O(1)) Effiziente Speicherung Gute Referenzlokalität (Daten liegen nahe beieinander im Speicher) Nachteile Kein effizientes Hinzufügen/Löschen von Array-Elementen Gefahr eines Systemcrash bei Überschreiten der Indexgrenzen

95 Einführung in die Programmierung Beispiel: Array von Objekten (1) // Implementierung auf Basis des Java-Array-Typs public class ObjFeld { private Object daten[] = null; public ObjFeld() {} public int laenge() { return (daten == null ? 0 : daten.length); } public Object element (int idx) { if (daten == null || idx = laenge()) throw new ArrayIndexOutOfBoundsException(); else return daten[idx]; }... }

96 Einführung in die Programmierung Beispiel: Array von Objekten (2) // Einfügen von Elementen public void einfuegen (int pos, Object o) { int i, num = laenge(); if (pos == -1) pos = num; Object ndaten[] = new Object[num + 1]; for (i = 0; i < pos; i++) ndaten[i] = daten[i]; ndaten[i++] = o; for (; i < num + 1; i++) ndaten[i] = daten[i - 1]; daten = ndaten; }

97 Einführung in die Programmierung Stack Definition Ein Stack, oft auch Kellerspeicher oder Stapelspeicher genannt, ist eine häufig (aber meist unbewusst) benutzte Datenstruktur in Programmen, die Daten als Stapel ablegt. Funktionsweise Ein Stack kann eine beliebige Menge von Elementen aufnehmen. Es gibt im Wesentlichen zwei Operationen, meist mit push und pop bezeichnet. Push legt ein Element auf den Stapel, pop holt ein Element vom Stapel (und entfernt dieses). Dabei wird nach dem LIFO-Prinzip (last in first out) gearbeitet, d.h. es wird immer das Element zurückgegeben, welches als letztes auf dem Kellerspeicher mit push abgelegt wurde. Die Theoretische Informatik unterscheidet hierbei zwischen einem echten Kellerspeicher, bei dem kein Element außer dem Obersten gelesen werden kann, und einem Stapel, bei dem ohne Veränderung der Daten jedes Element betrachtet werden kann (vergleichbar einem Lesezugriff auf einen Array).

98 Einführung in die Programmierung Schnittstelle: Stack void push(Object obj) legt das Objekt obj als oberstes Element auf dem Stack ab Object pop() nimmt das oberste Element vom Stack und gibt es zurück Object top() gibt das oberste Element des Stacks zurück, ohne es zu entfernen boolean isEmpty() liefert true, wenn keine Elemente auf dem Stack liegen, andernfalls false Beispiel public class Stack { public void push(Object obj) throws StackException {...} public Object pop() throws StackException {...} public Object top() throws StackException {...} public boolean isEmpty() {...} }

99 Einführung in die Programmierung Nutzung des Stack... Stack stack = new Stack(); try { // Elemente auf den Stack ablegen stack.push("Eins"); stack.push("Zwei"); stack.push("Drei"); // Elemente wieder vom Stack holen while (! stack.isEmpty()) { String s = (String) stack.pop(); System.out.println(s); } } catch (StackException exc) { System.out.println("Fehler: " + exc); }...

100 Einführung in die Programmierung Implementierung des Stack (1) verschiedene Implementierungen möglich hier über statisches Feld mit vorgegebener Kapazität notwendig: Behandlung des Überlaufs (StackException) public class Stack { Object elements[] = null; // Elemente int num = 0; // aktuelle Anzahl // Stack mit vorgegebener Kapazität public Stack(int size) { elements = new Object[size]; }... }

101 Einführung in die Programmierung Implementierung des Stack (2) 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; }

102 Einführung in die Programmierung Implementierung des Stack (3) public Object top() throws StackException { if (isEmpty()) throw new StackException(); return elements[num - 1]; } public boolean isEmpty() { return num == 0; }

103 Einführung in die Programmierung (Verkettete) Liste (1) Definition Eine (Verkettete) Liste als Datenstruktur hat folgende allgemeine, graphische Beschreibung Sie besteht aus Knoten, die zum einen den Wert eines Listen- elements und darüber hinaus strukturelle Informationen zur Art der Liste enthalten. Sie enthält gerichteten Kanten, die die Verbindung zwischen zwei Knoten referenzieren. Die Verbindung zwischen den Knoten einer Liste ist in der Weise gegeben, dass stets ein Knoten (mit Ausnahme des erste und letzten) genau einen Vorgänger (predecessor) und genau einen Nachfolger (successor) besitzt. Das erste Listenelement wird Listenkopf (head), der Rest Listenkörper (tail) genannt. Für die korrekte Erkennung des Listenendes besitzt das letzte Listenelement einen Listennullwert (null).

104 Einführung in die Programmierung Liste (2) Die gebräuchlichsten Listenformen sind die einfache und die doppelt verkettete Liste. Die einfach verkettete Liste hat die folgende allgemeine Form Die doppelt verkettete Liste hat diese Form

105 Einführung in die Programmierung Liste (3) Verarbeitungs- bzw. Speicherungsfunktionen auf dieser Datenstruktur sind das Einfügen eines Knoten in die (vorhandene) Liste, das Entfernen eines Knoten aus der Liste, das Ersetzen eines Knotenwertes innerhalb der Liste, die Veränderung der Knotenreihenfolge der Liste. Zugriffsfunktionen im weitesten Sinne sind für die Listen beispielsweise die Bestimmung der Listenlänge, die Suche nach einem vorgegebenen Knoteninhalt, die Bestimmung der Position eines bestimmten Listenelementes, die Frage, ob die Liste leer ist. Listen werden im allgemeinen verwendet für Informationen, die genau in dieser Reihenfolge benötigt werden, die Implementierung anderer Strukturen wie Stack oder Queue.

106 Einführung in die Programmierung Schnittstelle: Liste void addFirst(Object obj) fügt das Objekt obj als erstes Element in die Liste ein Object getFirst() liefert das erste Element der Liste Object removeFirst() entfernt das erste Element der Liste und gibt es gleichzeitig als Ergebnis zurück void addLast(Object obj) hängt das Objekt obj als letztes Element an die Liste an Object getLast() liefert das letzte Element der Liste Object removeLast() entfernt das letzte Element der Liste und gibt es gleichzeitig als Ergebnis zurück

107 Einführung in die Programmierung Implementierung der Listen-Knoten 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; } }

108 Einführung in die Programmierung Implementierung der Liste: Initialisierung public class List { class Node {... } private Node head = null; public List() { head = new Node(); }... }

109 Einführung in die Programmierung Implementierung der Liste: Einfügen public void addFirst(Object o) { // neuen Knoten hinter head einführen Node n = new Node(o, head.getNext()); head.setNext(n); } public void addLast(Object o) { Node l = head; // letzten Knoten ermitteln while (l.getNext() != null) l = l.getNext(); Node n = new Node(o, null); // neuen Knoten anfügen l.setNext(n); }

110 Einführung in die Programmierung Implementierung der Liste: Löschen public Object removeFirst() { if (isEmpty()) return null; Object o = head.getNext().getElement(); head.setNext(head.getNext().getNext()); return o; } public Object removeLast() { if (isEmpty()) return null; Node l = head; while (l.getNext().getNext() != null) l = l.getNext(); Object o = l.getNext().getElement(); l.setNext(null); return o; }

111 Einführung in die Programmierung Nutzung der Liste... List liste = new List(); liste.addFirst("Drei"); liste.addFirst("Zwei"); liste.addFirst("Eins"); liste.addLast("Vier"); liste.addLast("Fünf"); while (! liste.isEmpty()) System.out.println((String) liste.removeFirst());...

112 Einführung in die Programmierung Alternative Implementierung: Iterator-Konzept „Durchwandern“ von Kollektionen (Beliebigen Mengen) prinzipiell implementierungsabhängig: siehe Feld, Stack, Liste,... einheitliche Behandlung durch Iterator Objekt als abstrakter Zeiger in Kollektion Methoden zum Iterieren über Kollektion

113 Einführung in die Programmierung Iterator-Implementierung für Liste class List { class ListIter implements Iterator { private Node node = null; public ListIter() { node = head.getNext(); } public boolean hasNext() { return node != null; } public Object next() { if (! hasNext()) throw new NoSuchElementException(); Object o = node.getElement(); node = node.getNext(); return o; } } }

114 Einführung in die Programmierung Iterator-Nutzung für Liste import java.util.Iterator; class List {... public Iterator iterator() { return new ListIterator(); } java.util.Iterator iter = liste.iterator(); while (iter.hasNext()) { Object obj = iter.next(); // Verarbeite obj... }

115 Einführung in die Programmierung Bäume (1) Definition Ein Baum B besteht aus einer Menge von Knoten und einer Eltern-Kind- Beziehung zwischen Knoten mit den folgenden Eigenschaften Der Baum hat genau eine Wurzel (root r). Jeder Knoten v (vertex, node) hat genau einen Elternknoten u (parent). Der Knoten v ist ein Kindknoten (child) von u. Ein Knoten kann beliebig viele Kindknoten haben. Knoten ohne Kindknoten heißen Blätter oder externe Knoten des Baums. Alle anderen Knoten heißen interne Knoten.

116 Einführung in die Programmierung Bäume (2): Niveau und Höhe Niveau 0 Niveau 1 Niveau 2 Niveau 3 Höhe := größtes Niveau + 1

117 Einführung in die Programmierung Beispiel: Dateisystem in Unix

118 Einführung in die Programmierung Bäume (3) Definition Ein Baum, für den jeder Knoten höchstens zwei Kindknoten hat, heißt binärer Baum. Hat jeder Knoten entweder zwei oder keine Kindknoten, dann nennen wir den binären Baum regulär. Jeder Kindknoten eines binären Baums ist entweder ein linker oder ein rechter Kindknoten. Der Unterbaum eines linken Kindknotens heißt linker Unterbaum, der eines rechten Kindknotens heißt rechter Unterbaum.

119 Einführung in die Programmierung Beispiel: Entscheidungsbaum

120 Einführung in die Programmierung Implementierung der Baum-Knoten class TreeNode { TreeNode left = null, right = null; Object key; public TreeNode(Object o) { key = o; } public Object getKey() { return key; } public TreeNode getLeft() { return left; } public TreeNode getRight() { return right; } public void setLeft(TreeNode n) {left = n;} public void setRight(TreeNode n) {right = n;} public String toString() { return key.toString(); }

121 Einführung in die Programmierung Implementierung des binären Baums public class BinaryTree { private TreeNode head, nullNode; public BinaryTree() { head = new TreeNode(null); nullNode = new TreeNode(null); head.setRight(nullNode); nullNode.setRight(nullNode); nullNode.setLeft(nullNode); }... }

122 Einführung in die Programmierung Traversierung des binären Baums systematisches Durchlaufen aller Knoten des Baums

123 Einführung in die Programmierung Ausgewählte Algorithmen: Motivation Kennenlernen von Beispielalgorithmen, auch als Grundlage für praktische Übungen Vorbereitung der theoretischen Betrachtungen, etwa Komplexität von Algorithmen informelle Diskussion von Design-Prinzipien Eigenschaften und Probleme der Umsetzung in eine Programmiersprache

124 Einführung in die Programmierung Suchen Suchen ist eine der häufigsten Aufgaben in der Informatik Vielzahl von Lösungen für unterschiedlichste Aufgaben hier: Suchen in sortierten Folgen Annahmen Folge F als Feld von numerischen Werten Zugriff auf i-tes Element über F[i] nur Berücksichtigung des Suchschlüssels Beispiel Telefonbuch, Suche nach Namen, Beispielfolien in dieser Sammlung

125 Einführung in die Programmierung Sequentielle Suche: Algorithmus Pseudocode algorithm SeqSearch (F, k)  p Eingabe: Folge F der Länge n, Schlüssel k for i := 1 to n do if F[i] = k then return i; fi; Od; return NO_KEY;

126 Einführung in die Programmierung Sequentielle Suche: Aufwand

127 Einführung in die Programmierung Binäre Suche: Prinzip 1.Wähle den mittleren Eintrag m und prüfe ob gesuchter Wert in der ersten oder in der zweiten Hälfte der Liste ist. 2.Ist der mittlere Eintrag m der gesuchte Wert, beende die Suche. 3.Fahre rekursiv mit der Hälfte fort, in der sich der gesuchte Wert befinden muss. Beispiel

128 Einführung in die Programmierung Binäre Suche: Algorithmus Pseudocode algorithm BinarySearch (F, k)  p Eingabe: Folge F der Länge n, Schlüssel k u := 1; o := n; while u <= o do m := (u + o)/2; if F[m] = k then return m; else if k < F[m] then o := m − 1; else u := m + 1 fi; fi; od; return NO_KEY

129 Einführung in die Programmierung Binäre Suche: Aufwandsanalyse nach dem ersten Teilen der Folge: noch n/2 Elemente nach dem zweiten Schritt: n/4 Elemente nach dem dritten Schritt: n/8 Elemente... allgemein: im i-ten Schritt max. n/2i Elemente  log2 n Aufwand

130 Einführung in die Programmierung Vergleich der Suchverfahren

131 Einführung in die Programmierung Implementierung in Java public class Suche { public final static int NO_KEY = -1;... public static void main(String[] args) { if (args.length != 1) return; int[] f = { 2, 4, 5, 6, 7, 8, 9, 11 }; int k = Integer.parseInt(args[0]); System.out.println("Ergebnis: " + seqSuche(f, k)); }

132 Einführung in die Programmierung Implementierung in Java (1) Sequentielle Suche static int seqSuche(int[] array, int key) { for (int i = 0; i < array.length; i++) if (array[i] == key) return i; return NO_KEY; }

133 Einführung in die Programmierung Implementierung in Java (2) Binäre Suche static int binSuche(int[] array, int key) { int u = 0, o = array.length - 1; while (u <= o) { int m = (u + o) / 2; if (array[m] == key) return m; else if (array[m] > key) o = m - 1; else u = m + 1; } return NO_KEY; }

134 Einführung in die Programmierung Sortieren Grundlegendes Problem in der Informatik Aufgabe Ordnen von Dateien mit Datensätzen, die Schlüssel enthalten Umordnen der Datensätze, so dass klar definierte Ordnung der Schlüssel (numerisch/alphabetisch) besteht Vereinfachung: nur Betrachtung der Schlüssel, z.B. Feld von int-Werten Verfahren intern: in Hauptspeicherstrukturen (Felder, Listen) extern: Datensätze auf externen Medien (Festplatte, Magnetband)

135 Einführung in die Programmierung Sortieren durch Einfügen: Prinzip Idee Umsetzung der typischen menschlichen Vorgehensweise, etwa beim Sortieren eines Stapels von Karten: 1.Starte mit der ersten Karte einen neuen Stapel 2.Nimm jeweils nächste Karte des Originalstapels: füge diese an der richtigen Stelle in den neuen Stapel ein

136 Einführung in die Programmierung Sortieren durch Einfügen: Algorithmus Pseudocode algorithm InsertionSort (F) Eingabe: zu sortierende Folge F der Länge n for i := 2 to n do m := F[i]; j := i; // zu merkendes Element while j > 1 do if F[j − 1]  m then // Verschiebe F[j − 1] nach rechts F[j] := F[j − 1]; j := j − 1; else // Verlasse innere Schleife fi; F[j] := m; // Einfügeposition od;

137 Einführung in die Programmierung Beispiel: Sortieren durch Einfügen

138 Einführung in die Programmierung Sortieren durch Selektion Idee Suche jeweils größten Wert, und tausche diesen an die letzte Stelle; fahre dann mit der um 1 kleineren Liste fort. Pseudocode algorithm SelectionSort (F) Eingabe: zu sortierende Folge F der Länge n p := n; while p > 0 do g := Index des größten Elementes aus F im Bereich 1...p; Vertausche Werte von F[p] und F[g]; p := p − 1; od;

139 Einführung in die Programmierung Beispiel: Sortieren durch Selektion

140 Einführung in die Programmierung Sortieren durch Blubbern (BubbleSort) Idee Verschieden große aufsteigende Blasen („Bubbles“) in einer Flüssigkeit sortieren sich quasi von allein, da größere Blasen die kleineren „überholen“. Pseudocode algorithm BubbleSort (F) Eingabe: zu sortierende Folge F der Länge n do for i := 1 to n − 1 do if F[i] > F[i + 1] then Vertausche Werte von F[i] und F[i + 1]; od; until keine Vertauschung mehr aufgetreten;

141 Einführung in die Programmierung Beispiel: BubbleSort

142 Einführung in die Programmierung Sortieren durch Mischen (MergeSort) Idee 1.Teile die zu sortierende Liste in zwei Teile (divide and conquer). 2.Sortiere diese Teillisten (rekursives Verfahren!). 3.Mische die Ergebnisse. Mischen von zwei Folgen algorithm Merge (F 1, F 2 )  F Eingabe: zwei zu sortierende Folgen F 1, F 2 Ausgabe: eine sortierte Folge F F := leere Folge; while F 1 oder F 2 nicht leer do Entferne das kleinere der Anfangselemente aus F 1 bzw. F 2 ; Füge dieses Element an F an; od; Füge die verbliebene nichtleere Folge F 1 oder F 2 an F an; return F;

143 Einführung in die Programmierung MergeSort: Algorithmus algorithm MergeSort (F)  F S Eingabe: eine zu sortierende Folge F Ausgabe: eine sortierte Folge F S if F einelementig then return F; else Teile F in F 1 und F 2 ; F 1 := MergeSort (F 1 ); F 2 := MergeSort (F 2 ); return Merge (F 1, F 2 ); fi;

144 Einführung in die Programmierung Beispiel: MergeSort

145 Einführung in die Programmierung Sortieren durch Pivotelement (QuickSort) Idee 1.Ähnlich wie MergeSort durch rekursive Aufteilung. 2.Vermeidung des Mischvorgangs durch Aufteilung der Teillisten in zwei Hälften bezüglich eines Pivot-Elementes, wobei in einer Liste alle Elemente größer als das Referenzelement (Pivot-Element) sind, in der anderen Liste alle Elemente kleiner oder gleich sind.

146 Einführung in die Programmierung QuickSort: Algorithmus algorithm QuickSort (F, u, o) Eingabe: zu sortierende Folge F, untere und obere Grenze u, o if o > u then Bestimme Position p des Pivot-Elements; pn := Zerlege(F, u, o, p); QuickSort (F, u, pn − 1); QuickSort (F, pn + 1, o); fi;

147 Einführung in die Programmierung QuickSort: Zerlegen (1) Pivot-Element an Position p 1.Pivot-Element an das rechte Ende der Folge verschieben 2.Folge von links durchlaufen: wenn aktuelles Element  Pivot-Element: nach vorn tauschen sonst: weiter 3.Pivot-Element zurücktauschen Position des Pivot-Elementes kann verschoben sein!

148 Einführung in die Programmierung QuickSort: Zerlegen (2) algorithm Zerlege (F, u, o, p)  pn Eingabe:zu sortierende Folge F, untere und obere Grenze u, o, Position p des Pivot-Elements Ausgabe:neue Position pn des Pivot-Elements pn := u; pv := F[p]; Tausche F[p] und F[o]; // Pivot-Elem. nach rechts for i := u to o − 1 do if F[i]  pv then Tausche F[pn] und F[i]; pn := pn + 1; fi; od; Tausche F[o] und F[pn]; // Pivot-Element zurück return pn;

149 Einführung in die Programmierung Beispiel: QuickSort

150 Einführung in die Programmierung Implementierung in Java public class Sort {... public static void main(String[] args) { int[] array = new int[10]; for (int i = 0; i < 10; i++) array[i] = (int)(Math.random() * 100.0); insertionSort(array); for (int k = 0; k < array.length; k++) System.out.print(array[k] + " "); System.out.println(); }

151 Einführung in die Programmierung Sortieren: InsertionSort static void insertionSort(int[] array) { for (int i = 1; i < array.length; i++) { int marker = i; int temp = array[i]; // für alle Elemente links vom Marker-Feld while (marker > 0 && array[marker - 1] > temp) { // verschiebe alle größeren Elemente array[marker] = array[marker - 1]; marker--; } // setze temp auf das freie Feld array[marker] = temp; }

152 Einführung in die Programmierung Sortieren: BubbleSort static void bubbleSort(int[] array) { boolean swapped; do { swapped = false; for (int i = 0; i < array.length-1; i++) { if (array[i] > array[i + 1]) { // Elemente vertauschen swap (array, i, i + 1); swapped = true; } // solange Vertauschung auftritt } while (swapped); }

153 Einführung in die Programmierung Vertauschen: BubbleSort static void swap(int[] array, int idx1, int idx2) { int tmp = array[idx1]; array[idx1] = array[idx2]; array[idx2] = tmp; }

154 Einführung in die Programmierung Sortieren: QuickSort (1) static int partition(int[] array, int u, int o, int p) { int pn = u; int pv = array[p]; // Pivot-Element an das Ende verschieben swap(array, p, o); for (int i = u; i < o; i++) if (array[i] <= pv) swap(array, pn++, i); // Pivot-Element an die richtige Position kopieren swap(array, o, pn); // neue Pivot-Position zurückgeben return pn; }

155 Einführung in die Programmierung Sortieren: QuickSort (2) // Hilfsmethode zum rekursiven Sortieren static void qsort(int[] array, int u, int o) { // Pivot-Element bestimmen int p = (u + o) / 2; if (o > u) { // Feld zerlegen und Partitionen sortieren int pn = partition(array, u, o, p); qsort(array, u, pn−1); qsort(array, pn+1, o); } static void quickSort(int[] array) { qsort(array, 0, array.length − 1); }

156 Einführung in die Programmierung Vergleich der Sortierverfahren


Herunterladen ppt "Einführung in die Programmierung Vorlesung SS 2006 Paul Manthey."

Ähnliche Präsentationen


Google-Anzeigen