Praktische Informatik 1 Prof. Dr. H. Schlingloff 28. 1. 2008 8.3 Applets, Internetprogrammierung • Applets sind Java-Programme, die aus HTMLSeiten aufgerufen werden können • Virtuelle Java-Maschine als Browser-Plugin • Grund für den Erfolg von Java, neue Technologie der „Web Services“ • Aus Sicherheitsgründen eingeschränkte Rechte (z.B. Cookies statt Dateizugriff) Vorgehensweise • Erstellung in Eclipse package AppletDemo; import java.awt.*; import java.applet.*; public class HalloWelt extends Applet { public void paint (Graphics g) { g.drawString("Hallo Welt!", 30, 20); } } • Einbindung in Webseite: <applet code="AppletDemo.HalloWelt.class„ width=320 height=240></applet> Tips&Tricks • .class-Datei muss in mit Paketnamen benannten • Unterverzeichnis des Verzeichnisses der .html-Datei liegen Parameterübergabe aus HTML: public void paint (Graphics g) { String col = getParameter("farbe"); if (col==null) setBackground(Color.lightGray); else if(col.equals("blau")) setBackground(Color.blue); g.drawString(col+"e Welt!", 60, 80); } • Webseite ...</applet><param name="farbe" value = "grün"> Kapitel 9: Algorithmen und Datenstrukturen 9.1 Listen, Bäume, Graphen 9.2 Suchen und Sortieren 9.3 Graphalgorithmen Alg&DS… … wurden klassischerweise als „das“ Thema der praktischen Informatik betrachtet … Bedeutung rückläufig wegen umfangreicher Bibliotheken … Forschungsfragen und Überraschungseffekte … Kenntnis der Funktionsweise für Informatiker unerläßlich 9.1 Listen, Bäume, Graphen • rekursive Datentypen jedes Objekt gehört zu einer bestimmten Klasse - Beispiel: int i; Thread f; PKW herbie; Objekte können andere Objekte als Bestandteile enthalten - Beispiel: Auto enthält Tachostand kann ein Objekt andere Objekte der selben Klasse enthalten? rekursive Datenstrukturen • Rekursion in Delphi mit • • • Zeigern aufgelöst In Java gibt es keine Zeiger (-typen), aber es gibt Objekte Es ist erlaubt, dass ein Objekt eine Komponente vom selben Typ enthält wie das Objekt selbst Rekursionsende: null verkettete Listen • Listen sind endliche Folgen von Elementen • Beispiel für dynamische Datenstruktur: Im Unterschied zu Arrays können Listen beliebig wachsen und schrumpfen neue Elemente werden an die Liste angehängt nicht mehr benötigte Elemente können entfernt werden • Verkettete Listen kann man sich wie eine Perlenschnur vorstellen von jeder Perle gibt es eine Verbindung zur folgenden in den Perlen befindet sich die Information • Die Liste besteht aus Zellen: jede Zelle hat einen Inhalt, und einen Verweis auf die folgende Zelle Listen als Perlenschnur Drucken einer Liste class Zelle{ int inhalt; Zelle next; public String toString(){ return inhalt+((next==null)?"": " -> " + next.toString()); } } class Liste{ ... public String toString(){return anfang.toString();} } public class ListenAnwendung { static Liste l = new Liste(); public static void main(String[] args) { l.insert(101); l.insert(38); l.insert(42); System.out.println(l); } } Entfernen des ersten Elementes • Um das erste Element zu löschen, setzen wir den Anfang einfach auf das zweite Element: anfang 333 inhalt next 222 inhalt next 101 inhalt next anfang = anfang.next • Der vorherige Anfang ist damit nicht mehr zugreifbar! • Natürlich darf das nur ausgeführt werden, falls die Liste nicht leer ist Entfernen eines inneren Elementes • Um ein inneres Element zu löschen, verbinden wir die Vorgängerzelle mit der Nachfolgerzelle: • Die Liste wird dadurch verändert! • Das abgeklemmte Element wird irgendwann von der Speicherbereinigung entdeckt, der Platz wiederverwendet Entfernen des n-ten Elementes void removeFirst() { anfang = anfang.next; } void removeNth(int n) { if(anfang !=null) { Zelle v = anfang; while (v.next!=null && n>1) { v = v.next; n--;} if(v.next!=null) v.next = v.next.next; } } Achtung: removeFirst() ist nicht das selbe wie removeNth(1) weitere Listenoperationen int länge(){ int i = 0; Zelle z = anfang; while (z!=null) { i++; z=z.next; } return i; } boolean enthält(int n) { boolean gefunden = false; Zelle z = anfang; while (z!=null && !gefunden) { if (z.inhalt==n) gefunden=true; z=z.next; } Zelle suche(int n){ return gefunden; } Zelle z = anfang; while (z!=null) { if (z.inhalt==n) return z; z=z.next; } return z; } Realisierung von Kellern mit Listen class Stapel extends Liste { Stapel() {} Stapel(Zelle z) { anfang = z; } boolean isEmpty(){ return anfang==null; } Stapel push(int i) { Zelle z = new Zelle(i, anfang); return new Stapel(z);} Stapel pop() { return new Stapel(anfang.next); } int top() { return anfang.inhalt; } } Problem • Durch diese Art der Implementierung wird bei jedem push und pop ein neuer Listenanfang generiert wird von der Speicherbereinigung aufgesammelt trotzdem ein gewisser Effizienzverlust nichtfunktionale Implementierung Stapel pop() { return new Stapel(anfang.next); } Stapel push(int n) { Zelle z = new Zelle(n, anfang); return new Stapel(z); } Stapel popSE() { removeFirst(); return this; } Stapel pushSE(int n) { insert(n); return this; } Ausführung • Jetzt wird nur noch auf ein und derselben Liste gearbeitet! Unterschied? public class StapelDemo { Stapel s1 = new Stapel(); Stapel s2 = new Stapel(); int sampleMethod() { s1=s1.push(111).push(222).push(333); s2=s1.pop(); return s1.top(); } } Was passiert beim Austausch von pop durch popSE? Schlangen • Zur Implementierung von Schlangen braucht man • einen zusätzlichen Zeiger auf den Anfang der Schlange Um den Aufbau am Schlangenende und den Abbau am Anfang zu implementieren, wird die Verkettung sozusagen „umgedreht“ Realisierung von Schlangen public class Queue extends Liste { Zelle ende; boolean isEmpty(){ return anfang==null; } int head() { return anfang.inhalt; } void tail() {anfang=anfang.next; } void append(int n) { Zelle z = new Zelle(n, null); if (isEmpty()) { anfang = z; ende = z; } else { ende.next = z; ende = z; } } Doppelt verkettete Listen • Für Listen, die auf beiden Seiten zugreifbar sein • • sollen, bietet sich eine symmetrische Lösung an Für jede Zelle wird Nachfolger und Vorgänger in der Liste gespeichert Beim Einfügen und Löschen müssen die doppelten Verkettungen beachtet werden Sequenzen als doppelt verkettete Listen public class Sequenz { Item erstes, letztes; Sequenz() {} Sequenz(Item e, Item l) { erstes=e; letztes=l; } boolean isEmpty() { return (erstes==null); } int first (){ return erstes.inhalt; } Sequenz rest() { return new Sequenz(erstes.rechts.erstes,letztes); } Sequenz prefix(int i) { Item neu = new Item(); neu.inhalt = i; class Item{ if (this.isEmpty()) { int inhalt; return new Sequenz(neu,neu); } SeqInt links, else { neu.rechts = erstes.rechts; erstes.links = neu.links; return new Sequenz(neu, letztes); } …} rechts; }