Mittwoch, 24. März 2010
Aufgaben zu Verketteten Listen
Diese Aufgabe enthält mehrere Übungsbeispiele zu Listen. Es sollen verschiedenste Aufgabenstellungen mit verketteten Listen gelöst werden, um das Verständnis mit Beispielen zu vertiefen.
Welche Daten in den Listen gespeichert werden ist meist nicht so wichtig. Verwenden Sie Strings oder ganze Zahlen, wenn nichts anderes angegeben wird.
Erstellen Sie jeweils eine Klasse
Erstellen Sie für alle Funktionen passende Testfälle und fertigen Sie ggf. Skizzen an.
Machen Sie zwei Varianten:
Welche Daten in den Listen gespeichert werden ist meist nicht so wichtig. Verwenden Sie Strings oder ganze Zahlen, wenn nichts anderes angegeben wird.
Erstellen Sie jeweils eine Klasse
public class Liste
, wie in Verkettete Listen beschrieben mit den in der jeweiligen Aufgabenstellung geforderten Methoden. Für die Datenelemente erzeugen Sie eine Klasse public class Data
, welche einen ganzzahligen Wert (int key
) und einen String (String value
) aufnehmen kann.1. Am Ende einer (einfach verketteten) Liste einfügen und löschen.
Schreiben Sie die Funktionenvoid append(Data data); /* anhängen */ void delEnd(); /* entfernen des letzten Elements */Skizzieren Sie mehrere Listenbeispiele und entwickeln sie passende Testfälle (leere Liste, ein Element, 2 Elemente, 3 oder mehr Elemente).
2. Sortiertes Einfügen in eine doppelt verkettete Liste
Schreiben Sie eine Funktionvoid insert_sort(Data data);welche ein Element sortiert nach
key
in die doppelt verkettete Liste einfügt (Vorwärts- und Rückwärtsverkettung).3. Löschen eines bestimmten Elements
Schreiben Sie eine Funktionboolean del(Data data);welche ein Element mit dem gesuchten Inhalt löscht (meist wird nur ein
key
verwendet, hier können Sie aber einfach die Daten verwenden). del()
soll true
liefern, wenn das Element gefunden und gelöscht wurde.4. Ändern eines Elements in einer einfach verketteten Liste
Schreiben Sie eine Funktionvoid change(Data old, Data newdata);welche ein Element
old
aus der Liste nimmt, es durch die Werte von newdata
ersetzt und dieses Element dann wieder an geeigneter Stelle einfügt, sodass die Liste nach diesem Aufruf wieder sortiert ist (normalerweise betrifft das Enfernen und Wiedereinfügen nur denkey
).Erstellen Sie für alle Funktionen passende Testfälle und fertigen Sie ggf. Skizzen an.
5. Sortiertes Einfügen
Erstellen Sie ein Java-Programm, welches Namen von der Standardeingabe liest und sortiert in eine einfach verkettete Liste einträgt. BeiEOF
wird dann die Liste auf der Standardausgabe ausgegeben.Machen Sie zwei Varianten:
- Iteratives sortiertes Einfügen und iteratves Ausgeben
- Rekursives sortieres Einfügen und rekursives Ausgeben
Samstag, 20. März 2010
Teilnahme an der RobotChallenge 2010
Unser Team Robert nahm heute an der RobotChallenge 2010 teil. Leider nur ein Teilerfolg, aber lesen Sie hier mehr.
Labels: Robotik
Freitag, 19. März 2010
Probleme mit python's random
Wenn man Zufallszahlen benötigt oder Funktionen, die auf zufällige Zahlenfolgen basieren, verwendet man in Python das Modul
random
(ähnliche Module, Klassen oder Libraries gibt es im Prinzip für alle Programmiersprachen). Dahinter steckt keine echte Zufallszahlenerzeugung sondern vielmehr eine Funktion, welche Pseudozufallszahlen liefert, die sich statistisch wie Zufallszahlen verhalten.Manchmal benötigt man immer wieder die selbe Zahlenfolge (z.B. beim Testen). Das erreicht man durch Angabe eines "seeds" (Samen) bei der Methode
random.seed()
, z.B. random.seed(23)
. Damit wird der Zufallsgenerator mit diesem Wert initialisiert. Bei selbem seed bekommt man immer die selbe Folge von Pseudozufallszahlen. Verwendet man diese Funktion nicht, so wird (zumindest bei Python) automatisch die Systemzeit als Anfangswert genommen. Damit kann man die Folge nicht vorhersagen (für einen bestimmten Zeitpunkt schon, dann nimmt man diesen Zeitstempel einfach als seed).Nun zu meinem Problem mit
random
:Python 2.5.2 auf meinem Debian- Rechner, den ich regelmäßig auf neuen Stand bringe
>>> from random import seed, random
>>> seed("23")
>>> random()
0.41111702255082994
Python 2.5.1 auf der Dreambox
>>> from random import seed, random
>>> seed("23")
>>> random()
0.09256672412670508
Bis vor Kurzem waren die beiden Werte identisch. Mein Python-Programm verhielt sich auf der Dreambox genauso wie auf meinem Entwicklungsrechner.
Offensichtlich gab es da Änderungen (Korrekturen) in der Python-Bibliothek.
In der Dokumentation von Python kann man lesen, dass für den seed ganze Zahlen (
long
, int
) oder jedes "hashable" Objekt verwenden kann. Und dort dürfte das Problem liegen:Python 2.5.2
>>> "23".__hash__()
6400038450057767
Python 2.5.1
>>> "23".__hash__()
308105767
Es ist einiges an Zeit vergangen, bis ich dieses Problem identifizieren konnte, denn der Bytecode von Python ist auf jeder Maschine gleich (ähnlich der VM von Java). Es muss also m.E. an der Version liegen.
Als Lösung bietet sich an, direkt eine Zahl zu verwenden:
Python 2.5.2
>>> seed(23)
>>> random()
0.92486525162594524
Python 2.5.1
>>> seed(23)
>>> random()
0.92486525162594524
Labels: allgemeines, Fehler, Python
Donnerstag, 18. März 2010
Kompetenzmatrix - was muss ein Programmierer können?
Unter folgendem Link sind die Kompetenzstufen von Programmierern ganz gut zusammengefasst.
Es ist ein weiter Weg von Stufe 0 auf Stufe 3.
Labels: allgemeines, Links
Samstag, 13. März 2010
Android Grundlagen der Programmierung
Es gibt ein deutsches Buch zum Thema Android Programmierung, das momentan überarbeitet wird und "nur" das Android SDK bis 1.5 behandelt. Aber es ist frei als Download erhältlich.
Link zur Buch Seite: http://www.androidbuch.de/
Download von Chip: http://www.chip.de/
Es ist auch in der Schule am edvoftp zu finden /home/software/android.
Donnerstag, 11. März 2010
UrlyBird-2010 - PR5
Die Aufgabenstellung zur Übung für die Projektwoche finden Sie am bscw - ich habe dazu alle Schüler der Klasse zum Verzeichnis PR5-2010 eingeladen. Sie finden dort eine Datei
urlybird-2010.jar
, welche im Verzeichnis Angabe
eine PDF-Datei mit der Angabe/Anleitung zu diesem Beispiel enthält.Der Abgabetermin ist für alle der 22. April 2010.
Alle weiteren Informationen finden Sie in dem Archiv bzw. in der PDF-Datei.
Mittwoch, 10. März 2010
Verkettete Listen
Folgendes Bild stellt das Prinzip der verketteten Listen dar. Wir benötigen einen Anker (pAnker), der auf das erste Element "zeigt". Jedes Element "zeigt" auf einen Nachfolger. Nur das letzte Element hat keinen Nachfolger und enthält daher
In Java könnte das etwa so formuliert werden:
Folgendes Listing zeigt eine mögliche Implementierung einer einfach verketteten Liste sowie die Verwendung einer solchen Liste als Stack. Neue Elemente werden einfach vorne eingefügt:
Da bei obigem Beispiel in der Methode
Es folgt nun eine etwas andere Implementierung von Elementen (
Als Daten werden einfach Strings verwendet.
Das Anhängen von Elementen ist hier effizienter gelöst durch die Verwendung von
null
.In Java könnte das etwa so formuliert werden:
class Element {
Element next;
int data;
Element(int data) {
this.data = data;
}
}
Element anker = null; // leere Liste
Element n = new Element(1);
n.next = anker;
anker = n;
n = new Element(2);
n.next = anker;
anker = n;
n = new Element(3);
n.next = anker;
anker = n;
System.out.println("liste");
for (Element e = anker; e != null; e = e.next) {
System.out.println(e.data);
}
// 1. Element entfernen
anker = anker.next;
System.out.println("liste");
for (Element e = anker; e != null; e = e.next) {
System.out.println(e.data);
}
Folgendes Listing zeigt eine mögliche Implementierung einer einfach verketteten Liste sowie die Verwendung einer solchen Liste als Stack. Neue Elemente werden einfach vorne eingefügt:
public class Liste {
private class Element {
Element next;
int data;
Element(int data) {
this.data = data;
}
}
private Element anker = null;
// private Element ende = null;
public void append(int data) {
if (anker == null) {
anker = new Element(data);
} else {
// suche Ende
Element e = anker;
while (e.next != null) {
e = e.next;
}
// e ist das letzte Element (Ende)
e.next = new Element(data);
}
}
public void insertFirst(int data) {
Element n = new Element(data);
n.next = anker;
anker = n;
}
public void deleteFirst() {
assert (anker != null);
anker = anker.next;
}
public void printList() {
System.out.print("[");
for (Element e = anker; e != null; e = e.next) {
System.out.print(e.data + " ");
}
System.out.println("]");
}
public void push(int data) {
insertFirst(data);
}
public int pop() {
assert (anker != null);
Element e = anker;
anker = anker.next;
return e.data;
}
public boolean isEmpty() {
return anker == null;
}
/**
* @param args
*/
public static void main(String[] args) {
Liste liste = new Liste();
liste.printList();
// liste.insertFirst(1);
// liste.insertFirst(2);
// liste.insertFirst(3);
liste.append(1);
liste.append(2);
liste.append(3);
liste.printList();
liste.deleteFirst();
liste.printList();
Liste stack = new Liste();
stack.push(23);
stack.push(3);
while (!stack.isEmpty()) {
System.out.println(stack.pop());
}
}
}
Da bei obigem Beispiel in der Methode
append()
immer das Ende der Liste gesucht wird, ist das Anhängen von Elementen etwas aufwändig, vor allem, wenn die Liste schon länger ist. Dies kann man verbessern, indem man auch das Ende der Liste mitspeichert.Es folgt nun eine etwas andere Implementierung von Elementen (
Node
) und einer Liste (Liste
), welche als Stack oder als Queue verwendet werden kann. Hier werden immer Objekte vom Typ Node
in der Liste manipuliert.
public class Node {
Node next;
String data;
public Node(String data) {
this.data = data;
}
public Node() {
data = null;
}
public String toString() {
return data;
}
}
Als Daten werden einfach Strings verwendet.
public class Liste {
private Node anker = null;
private Node last = null;
/**
* hängt Knoten n am Ende der Liste an (für Queue).
*
* @param n
* neuer Knoten
*/
public void put(Node n) {
if (last == null) { // erstes Element
anker = n;
last = n;
} else {
last.next = n;
last = n;
}
}
/**
* liefert erstes Element und entfernt dieses aus der Liste
*
* @return erster Knoten oder null
*/
public Node get() {
Node ret = null;
if (anker != null) {
ret = anker;
anker = anker.next;
if (anker == null) { // war das das letzte Element?
last = null;
}
}
return ret;
}
/**
* pop() für Verwendung als Stack.
*
* @return erstes Element
*/
public Node pop() {
return get();
}
/**
* fügt Knoten vorne ein (für Stack).
*
* @param n
* neuer Knoten
*/
public void push(Node n) {
if (anker == null) {
anker = n;
last = anker;
} else {
n.next = anker;
anker = n;
}
}
/**
* liefert Liste als String.
*
* @return "[erstes,zweites,...]", "[]" bei leerer Liste (KEINE Leerzeichen)
*/
public String toString() {
String ret = "[";
Node n;
for (n = anker; n != null && n.next != null; n = n.next) {
ret += n + ",";
}
if (n != null) {
ret += n;
}
ret += "]";
return ret;
}
}
Das Anhängen von Elementen ist hier effizienter gelöst durch die Verwendung von
last
, einer Referenz auf das letzte Element.einfache erkennende Automaten, implementiert mit Zustandstabelle
Erstellen Sie jeweils eine Klasse, die einen Automaten zur Erkennung von
Die Automaten sollen jeweils eine Methode
- Telefonnummern mit Vorwahlen (/) und Durchwahlen (-)
- Postleitzahlen
- Autokennzeichen (österreichische)
Die Automaten sollen jeweils eine Methode
implementieren, welche
boolean accept(String input)
true
liefert, wenn der Automat den String input
akzeptiert.Beispiele für Telefonnummern:
27871 ... ohne Vorwahl (im Ort), ohne Durchwahl
27871-200 ... ohne Vorwahl mit Durchwahl
02622/27871 ... mit Vorwahl ohne Durchwahl
02622/27871-200 ... mit Vorwahl mit Durchwahl
+432622/27871 ... mit Vorwahl ohne Durchwahl
+432622/27871-200 ... mit Vorwahl mit Durchwahl
+43 2622 / 27 8 71 - 200 ... mit Vorwahl mit Durchwahl und eingestreuten Leerzeichen
Beispiele für Postleitzahlen:
2700, A-2700, D-23790, F-23091
Beispiele für Autokennzeichen:
W123X, L INZ23, WU123A, W 34597A, GFRAST2, GF RAST3
Nach dem Ortskennzeichen (1 bis 2 Buchstaben) darf ein Leerzeichen stehen. Danach kommt eine Reihe von Buchstaben und dann eine Reihe von Ziffern oder zuerst Ziffern und dann Buchstaben. Ungültig wäre z.B. W2BU3.
einfache erkennende Automaten, implementiert mit switch
Erstellen Sie jeweils eine Klasse, die einen Automaten zur Erkennung von
Die Automaten sollen jeweils eine Methode
- Telefonnummern mit Vorwahlen (/) und Durchwahlen (-)
- Postleitzahlen
- Autokennzeichen (österreichische)
switch
-Statements.Die Automaten sollen jeweils eine Methode
implementieren, welche
boolean accept(String input)
true
liefert, wenn der Automat den String input
akzeptiert.Beispiele für Telefonnummern:
27871 ... ohne Vorwahl (im Ort), ohne Durchwahl
27871-200 ... ohne Vorwahl mit Durchwahl
02622/27871 ... mit Vorwahl ohne Durchwahl
02622/27871-200 ... mit Vorwahl mit Durchwahl
+432622/27871 ... mit Vorwahl ohne Durchwahl
+432622/27871-200 ... mit Vorwahl mit Durchwahl
+43 2622 / 27 8 71 - 200 ... mit Vorwahl mit Durchwahl und eingestreuten Leerzeichen
Beispiele für Postleitzahlen:
2700, A-2700, D-23790, F-23091
Beispiele für Autokennzeichen:
W123X, L INZ23, WU123A, W 34597A, GFRAST2, GF RAST3
Nach dem Ortskennzeichen (1 bis 2 Buchstaben) darf ein Leerzeichen stehen. Danach kommt eine Reihe von Buchstaben und dann eine Reihe von Ziffern oder zuerst Ziffern und dann Buchstaben. Ungültig wäre z.B. W2BU3.
Abonnieren Posts [Atom]