Liste

Werbung
Übung Softwareentwicklung 1
für Wirtschaftsinformatik
Listen
Dipl.-Ing. Kerstin Altmanninger
Wintersemester 2008/2009
Mittwoch, 17.12.2008
Überblick
•
Dynamische Datenstrukturen (allgemeine Einführung)
•
Listen
– Verketten von Knoten
– Charakteristiken von Listen
– Unsortierte, einfach verkettete Liste
– Sortierte, einfach verkettet Liste
•
Beispiele
– „Stack“ als einfach verkettete Liste
– „PhoneBook“ als sortierte, doppelt verkettete Liste
2/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Dynamische Datenstrukturen
•
Datenstrukturen, die aus verketteten Objekten (Knoten) bestehen
→ dynamisch
– Knoten werden zur Laufzeit (also dynamisch) mittels „new“ erzeugt und dann
verkettet
– Die so erzeugten Datenstrukturen können (so lange Speicher vorhanden ist)
dynamisch wachsen und schrumpfen
•
Beispiele für dynamische Datenstrukturen:
– Listen
– Bäume
– Graphen
Liste
Baum
Graph
3/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Verketten von Knoten (1/2)
•
Eine Liste besteht aus Knoten, die man miteinander verketten muss
•
Beispiel einer Klasse Node, wie man zwei Knoten über Zeiger miteinander
verkettet:
class Node {
int val;
//Feld stellt irgendwelche Daten dar
Node next;
//Feld entspricht einem Zeiger
Node(int val) { //Konstruktor
this.val = val;
next = null;
}
}
•
Mit dem Feld, der einen Zeiger darstellt (Node next;) können NodeObjekte miteinander verkettet werden
•
Das Feld next zeigt entweder auf ein anderes Node-Objekt oder hat den
Wert null
4/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Verketten von Knoten (2/2)
a
•
Beispiel:
1
Node a = new Node(1);
Node b = new Node(2);
•
•
b
2
Gegeben: 2 Node-Objekte, deren Adressen in den Variablen a und b
gespeichert sind
Verkettung der beiden Node-Objekte:
a.next = b;
a
b
1
2
•
Die Zuweisung (b.next=null;) kann man sich sparen, da ein neu
erzeugtes Node-Objekt automatisch mit null initialisiert wird
•
Erreichung der beiden Knoten:
– Der erste Knoten kann über a erreicht werden
– Der zweite Knoten kann über b oder ueber a.next erreicht werden
5/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Charakteristiken von Listen
•
Zur Realisierung einer Liste sind 2 Klassen notwendig:
– Eine reine Datenklasse fuer die Listenknoten
– Eine Klasse die die eigentliche Liste realisiert
(enthält Operationen wie das Einfügen, Löschen und Suchen von Knoten)
•
Die Klasse, die die Liste realisiert, kann folgende Ausprägungen aufweisen:
– Zeiger auf den ersten Knoten in der Liste (head) und optional einen Zeiger auf
den letzten Knoten in der Liste (tail)
– Unsortiert- vs. Sortiert
– Einfach verkettet vs. doppelt verkettet
Unsortierte, einfach verkettete Liste mit
einem Zeiger auf den ersten und einen
zweiten Zeiger auf den letzten Listenknoten:
head
tail
Sortierte, doppelt verkettete Liste mit einem
Zeiger auf den ersten Listenknoten:
head
3
12
3
8
12
8
6/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
•
Reihenfolge der Knoten entspricht nicht der Sortierreihenfolge ihrer
Datenfelder
Möglichkeit A
•
Möglichkeit B
Beispiel:
head
head
12
•
3
8
tail
12
3
8
Klassendiagramm:
List
head:Node
insert(x:int)
append(x:int)
delete(x:int)
search(x:int):Node
*
Node
val: int
next: Node
List
head:Node
tail:Node
insert(x:int)
append(x:int)
delete(x:int)
search(x:int):Node
*
Node
val: int
next: Node
7/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Einfügen von Elementen
•
Wenn man eine neue Zahl in die Liste einfügen möchte, muss man
1. einen neuen Knoten erzeugen, in dem wir die Zahl speichern und
2. diesen Knoten in die Liste einhängen
•
Knoten kann an eine beliebige Position eingefügt werden
•
Bei „unsortierten Listen“ unterscheidet man zwei Möglichkeiten:
a) Einfügen am Anfang der Liste
b) Einfügen am Ende der Liste
8/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Einfügen von Elementen am Anfang der Liste
A
Arbeitsweise der Listenoperation insert(int x):
Initialzustand:
insert(12);
insert(3);
head
head
head
12
3
12
class List {
Node head = null; //Liste ist zu Beginn leer
...
void insert(int val) {
Node p = new Node(val); //Erzeugung eines neuen Knoten p
p.next = head; //Der next Zeiger von p wird auf den head gesetzt
head = p;
//p wird zum neuen Listenanfang
}
...
}//end class List
9/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Einfügen von Elementen am Ende der Liste A
Arbeitsweise der Listenoperation append(int x):
Initialzustand:
append(12);
append(3);
head
head
head
12
12
3
...
void append(int val) {
Node p = new Node(val);
Node cur = head;
if (head == null) head = p; //Liste ist leer
else {
while (cur.next != null) cur = cur.next; //Suche nach Listenende
cur.next = p; //Neuer Knoten wird an das Listenende angehaengt
}
}
...
10/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Einfügen von Elementen am Ende der Liste B
Arbeitsweise der Listenoperation append(int x):
Initialzustand:
append(12);
head
head
tail
tail
12
append(3);
tail
head
12
3
...
void append(int val) {
Node p = new Node(val);
if (head == null) head = p; //Liste ist leer
else tail.next = p; //Einfuegen des neuen Knoten an das Ende der Liste
tail = p;
//tail auf das letzte Element setzen
}
...
11/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Suchen von Elementen
•
Wenn ein gesuchtes Element in der Liste enthalten ist, soll ein Zeiger auf
den Knoten zurückgegeben werden
•
Wenn es nicht enthalten ist soll null zurückgegeben werden
class List {
Node head = null;
...
Node search(int val) {
Node tmp = head; //Der Knoten tmp wird auf head gesetzt
//Durchlaufen der Liste
while (tmp!=null && tmp.val!=val) tmp = tmp.next;
//Durchlauf ist beendet, falls man am Ende der Liste angekommen ist
//oder falls der Knoten tmp den gesuchten Wert enhaelt
return tmp;
}
...
}//end class List
12/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Löschen von Elementen (1/2)
•
A
Schritt 1: Den zu löschende Knoten suchen (delete(3);)
del
head
12
•
3
8
Schritt 2: Der next Zeiger des Vorgängerknotens muss auf den Nachfolger
des zu löschenden Knotens gesetzt werden
prev
del
head
12
3
8
13/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Unsortierte, einfach verkettete Liste
Löschen von Elementen (2/2)
A
prev
del
class List {
head
Node head = null;
...
3
8
12
void delete(int val) {
Node del = head;
Node prev = null;
//Suchen des Knotens der geloescht werden soll
while (del!=null && del.val!=val) {
prev = del;
del = del.next;
}
//Der zu loeschende Knoten wurde gefunden
if (del!=null) {
//Falls der Knoten auf den head zeigt geloescht werden soll,
//muss der Zeigen von head modifiziert werden
if (del==head) head = del.next;
//Ansonsten: Verwendung des prev Objekts
else
prev.next = del.next;
}
}
...
}//end class List
14/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Sortierte, einfach verkettete Liste
•
Reihenfolge der Knoten entspricht der Sortierreihenfolge ihrer Datenfelder
•
Beispiel einer sortierten Liste:
head
8
3
•
Klassendiagramm:
SortedList
head:Node
insert(x:int)
delete(x:int)
search(x:int):Node
*
12
Node
val: int
next: Node
15/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Sortierte, einfach verkettete Liste
Einfügen von Elementen
Beim Einfügen von Elementen muss die Sortierreihenfolge erhalten bleiben
Schritt 1: Einfügeposition suchen (insert(5);)
head
8
3
prev
12
cur
Schritt 2: Neuen Knoten mit Element einfügen
head
5
3
prev
newNode
8
12
cur
16/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Sortierte, einfach verkettete Liste
Einfügen von Elementen (2/2)
void insert(int val) {
Node cur = head;
Node prev = null;
//Suchen der Einfuegeposition
while(cur!=null && cur.val<val) {
prev = cur;
cur = cur.next;
}
head
5
3
prev
newNode
8
12
cur
//Erzeugung des neuen Knoten
Node newNode = new Node(val);
//Einfeugen entweder am Ende der Liste if (p==null) oder
//an zwischen den Knoten auf die prev und cur zeigen.
//1. next-Zeiger von newNode wird auf das cur-Objekt gesetzt.
newNode.next = cur;
//2. Falls Liste leer ist muss newNode auf das head-Objekt zugewiesen werden
//falls die Liste nicht leer ist, wird der next-Zeiger von prev auf
//newNode gesetzt
if (cur == head) head = newNode;
else
prev.next = newNode;
}//end method insert
17/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Sortierte, einfach verkettete Liste
Suchen von Elementen
Statt: tmp.val!=val
Node search(int val) {
Die komplette Liste muss
nicht traversiert werden!!!
Node tmp = head;
while (tmp != null && tmp.val < val) {
tmp = tmp.next;
}
if (tmp.val==val) return tmp;
else
return null;
}//end method search
18/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Sortierte, einfach verkettete Liste
Löschen von Elementen
Statt: del.val!=val
void delete(int val) {
Die komplette Liste muss
nicht traversiert werden!!!
Node del = head;
Node prev = null;
//Suchen des Knotens der geloescht werden soll
while (del != null && del.val < val) {
prev = del;
del = del.next;
}
//Der zu loeschende Knoten wurde gefunden
if (del.val==val) {
//Falls der Knoten auf den head zeigt geloescht werden soll,
//muss der Zeigen von head modifiziert werden
if (del==head) head = del.next;
//Ansonsten: Verwendung des prev Objekts
else
prev.next = del.next;
}
}//end method delete
19/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Beispiel
„Stack“ als einfach verkettete Liste (1/4)
•
Klasse Stack wurde in EH06 mittels eines Arrays realisiert
Stack()
push(…)
stack
•
pop()
length
Da wir damals die Klasse Stack mittels Datenabstraktion (durch die Verwendung der
Sichtbarkeitsattribute private und public) implementiert wurde, können wir die
Implementierung einfach durch eine Liste auswechseln, ohne das Verändrungen in
anderen Programmen, die auf unsere Klasse Stack zugreifen vorgenommen werden
müssen!!!
Stack()
push(…)
pop()
top
20/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Beispiel
„Stack“ als einfach verkettete Liste (2/4)
public class Stack {
//Knoten der Liste:
class StackElement {
Felder
//Array:
private String[] stack;
private int length;
private String value;
StackElement next;
//List:
private StackElement top;
Konstruktor
//Array:
public Stack() {
stack = new String[100];
length = 0;
}
StackElement(String value) {
this.value = value;
next = null;
}
}
//List (optional):
public Stack() {
StackElement top = null;
}
...
}
21/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Beispiel
„Stack“ als einfach verkettete Liste (3/4)
public class Stack {
Einfügen von Elementen
in den Stack
...
//Array:
public void push (String item) {
if (length<stack.length) stack[length++] = item;
else System.out.println("Stack is full!");
}
//List:
public void push (String value) {
StackElement newElement = new StackElement(value);
newElement.next = top;
top = newElement;
}
...
}
22/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Beispiel
„Stack“ als einfach verkettete Liste (4/4)
public class Stack {
...
Löschen von Elementen aus
dem Stack
//Array:
public String pop() {
if (length!=0) return stack[--length];
else return null;
}
//List:
public String pop() {
if (top!=null) {
StackElement tmp = top;
top = top.next;
return tmp.value;
}
else return null;
}
}
23/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Beispiel
Sortierte, doppelt verkettete Telefonliste
•
Beispiel einer sortierten, doppelt verketteten Telefonliste:
head
•
Emilia
+43702468
Julian
+4367644432
Xaver
+436641233
tail
Klassendiagramm:
PhoneBook
name: String
head: PhoneBookEntry
tail: PhoneBookEntry
PhoneBook(name:String)
insert(name:String, phoneNumber:String):boolean
search(name:String):PhoneBookEntry
delete(name:String):boolean
update(name:String, phoneNumer:String):boolean
findPrevEntry(name:String):PhoneBookEntry
print()
*
PhoneBookEntry
name: String
phoneNumber: String
next: PhoneBookEntry
prev: PhoneBookEntry
PhoneBookEntry(name:String, phoneNumber:String)
toString():String
print()
lessThan(entry:PhoneBookEntry):boolean
lessThan(name:String):boolean
greaterThan(entry:PhoneBookEntry):boolean
equalsName(entry:PhoneBookEntry):boolean
equalsName(name:String):boolean
24/24
SWE1 Übung – EH8
DI Kerstin Altmanninger
Herunterladen