Übung: Algorithmen und Datenstrukturen SS 2007

Werbung
Übung: Algorithmen und Datenstrukturen
SS 2007
Prof. Lengauer
Sven Apel, Michael Claÿen, Christoph Zengler, Christof König
Blatt 3
Votierung in der Woche vom 14.05.0718.05.07 Aufgabe 6
Kopieren von Arrays
In Java sollen in einem Array Objekte gespeichert werden, die die Koordinaten
eines Punktes in der Ebene enthalten:
public class Point {
public double x;
public double y;
public Point(double x, double y) {
this.x = x;
this.y = y;
}
}
Überlegen Sie sich, wie Sie eine komplette Kopie (deep copy) des Arrays erzeugen
können und welche Ansätze nicht funktionieren würden, z. B. für ein Array a
soll b die Kopie sein:
Point[] a = new Point[3];
a[0] = new Point(0,0);
a[1] = new Point(1,1);
a[2] = new Point(2,2);
Point[] b;
/* ... */
Lösung:
1. Referenz zuweisen: a und b zeigen auf dasselbe Array (Bild malen).
b = a;
1
2. Referenzen der einzelnen Punkte zuweisen: a und b zeigen auf verschiedene
Arrays. Allerdings zeigen a[0] und b[0] immer noch auf dasselbe PointObjekt (Indizes 1 und 2 genauso).
b = new Point[3];
for(int i = 0; i < b.length; b++)
b[i] = a[i];
3. Methode clone aufrufen: siehe 2 (auch wenn Point vom Typ Cloneable
ist)
Point[] b = a.clone();
4. Systemfunktion nutzen: siehe 2.
b = new Point[3];
System.arraycopy(a, 0, b, 0, a.length);
5. Array and einzelne Point-Objekte jeweils neu anlegen: erzeugt eine komplette Kopie.
b = new Point[3];
for(int i = 0; i < b.length; b++) {
b[i] = new Point(a[i].x, a[i].y);
Aufgabe 7
Arrays und Listen
Aufgabe ist es, eine Datenstruktur Buffer mit folgenden Operationen zu implementieren:
• void insert(int i, Element e) fügt an der i-ten Position ein Element
in den Puer ein, ohne dass dabei andere Elemente überschrieben werden.
Es ist darauf zu achten, nicht über das bisherige Ende des Puers hinauszuschreiben. (Tipp: Verwenden Sie im Falle der Array-basierten Implementierung eine Variable size, die für die aktuelle Gröÿe des Puers
steht.)
• void push_back(Element e) fügt ein Element an das Ende des Puers
an, ohne dass dabei andere Elemente überschrieben werden.
• void push_front(Element e) fügt ein Element vor dem bisher ersten
Element des Puers ein, ohne dass dabei andere Elemente überschrieben
werden.
Verwenden Sie als interne Speicherstruktur (a) ein Array und (b) eine einfach
verkettete Liste. Geben sie jeweils an, welche Zeitkomplexität die einzelnen Operationen haben. (Tipp: Wieviele elementare Rechenschritte benötigt die Ausführung einer Operation ungefähr?)
Lösung:
Implementierung basierend auf einem Array:
2
class ArrayBuffer {
Element[] buffer = new Element[42];
int size = 0;
void insert(int i, Element e) {
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// ca. O(n) Verschiebe-Operationen
// Puffer Vergroessern wird von Verschiebe-Operationen dominiert
//
Element tmpElement;
if(buffer.length <= size+1) {
resizeBuffer();
}
int pos = i;
Element currElement = buffer[pos];
Element nextElement;
buffer[pos] = e;
}
while (currElement != null) {
nextElement = buffer[pos+1];
pos++;
buffer[pos] = currElement;
currElement = nextElement;
}
size++;
void push_back(Element e) {
}
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// hier ueberwiegt das Vergroessern des Puffers,
// weil beim Einfuegen am Ende des Puffers keine Elemente verschoben
// werden muessen: -> O(log n)
// (Verdoppeln nur in logarithmisch vielen Schritten)
//
if(buffer.length <= size+1) {
resizeBuffer();
}
insert(size, e);
size++;
void push_front(Element e) {
3
}
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// ca. O(n) Verschiebe-Operationen
// Puffer Vergroessern wird von Verschiebe-Operationen dominiert
//
if(buffer.length <= size+1) {
resizeBuffer();
}
insert(0, e);
size++;
private void resizeBuffer() {
Element[] newBuffer = new Element[buffer.length * 2];
for (int pos = 0; pos < buffer.length; pos++) {
newBuffer[pos] = buffer[pos];
}
}
buffer = newBuffer;
}
Lösung:
Implementierung basierend auf einer Liste:
class ListBuffer {
ElementList buffer = new ElementList();
void insert(int i, Element e) {
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// ca. O(n) Weitersetzen des Zeigers in der linked list
//
Node currNode = buffer.getHead();
Node newNode = new Node(e);
if (i == 0) {
// fuege neues Element am Kopf der Liste ein:
newNode.setNext(currNode);
buffer.setHead(newNode);
} else {
for (int pos=0; pos < i-1; pos++) {
currNode = currNode.getNext();
4
}
}
}
Node tmpNode = currNode.getNext();
currNode.setNext(newNode);
newNode.setNext(tmpNode);
void push_back(Element e) {
}
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// ca. O(n) Weitersetzen des Zeigers in der linked list
// (der Unterschied zur insert Operation kann hier
// naeherungsweise vernachlaessigt werden)
//
// Alternative (sehr relevant in der Praxis!):
// Verwendung eines Zeigers fuer das Ende der Liste
// -> O(1) push_back moeglich!
Node currNode = buffer.getHead();
for (int pos=0; pos < buffer.size(); pos++) {
currNode = currNode.getNext();
}
currNode.setNext(new Node(e));
void push_front(Element e) {
}
// Komplexitaet pro eingefuegtes Element
// bei Puffer der Laenge n:
// ca. O(n) Weitersetzen des Zeigers in der linked list
//
insert(0, e);
}
Aufgabe 8
Listen durchlaufen
Stellen Sie sich vor, Sie haben eine Java-Implementierung einer Notizliste gegeben:
LinkedList<String> notes = new LinkedList<String>();
notes.add("note 1");
notes.add("note 2");
notes.add("note 3");
notes.add("note 4");
5
/* ... */
Überlegen Sie sich, wieviele verschiedene sinnvolle Möglichkeiten existieren, die
Liste in Java zu durchlaufen. Zeigen Sie, wie eine solche Liste unter Verwendung
der unten stehenden Mechanismen durchlaufen werden kann:
(a) for-Schleife (for-each-Schleife)
(b) while-Schleife und Zugri über Index
(c) while-Schleife und Zugri über Iterator
Lösung:
(a) for-Schleife (for-each-Schleife)
for(String note : notes) {
System.out.println(note);
}
(b) while-Schleife und Zugri über Index
int i = 0;
while(i < notes.size()) {
System.out.println(notes.get(i++));
}
(c) while-Schleife und Zugri über Iterator
Iterator<String> it = notes.iterator();
while(it.hasNext())
System.out.println(it.next());
6
Herunterladen