9.3 Traversieren und Suchen

Werbung
9.3 Traversieren und Suchen
Vor.:
Von einer „Wurzel“ w aus seien alle Ecken erreichbar
Def.:
Die Expansion X(w) des Graphen G=(E,K) ist
a) w selbst, wenn w keine Nachfolger hat; sonst:
b) mit den Nachfolgern {v1, v2, .....} der ungeordnete
Vielwegbaum (w, {X(v1), X(v2), .....})
(ist unendlich, wenn G Zyklen bzw. Kreise enthält!)
a
b
a
b
c
d
d
b
c
alp3-9.3
b
c
c
a
a
b
c
d1
9.3.1 Tiefendurchlauf
Def.:
Tiefendurchlauf von G ab w = Durchlauf von X(w)
in Präordnung mit Ignorierung von Unterbäumen mit
bereits besuchter Wurzel (wenn der Graph kein Baum ist!)
(Entsprechend: Tiefensuche nach Ecke mit Eigenschaft e)
Besuchte Knoten werden markiert und dadurch wiedererkannt!
a
b
a
b
c
d
d
b
c
alp3-9.3
b
c
c
a
a
b
c
d
package Graph; // all nodes should be considered
//
to form ONE graph (see 9.2.3)
// not generic - for easier presentation
public class Node {
private boolean visited;
private final Set<Node> succ = new TreeSet<Node>();
.....
// just mark all reachable nodes, no further action:
public void depthFirstTraversal(){
if(!visited) {
visited = true;
for(Node n: succ) n.depthFirstTraversal(); }
}
}
Bemerkungen:  depthFirstTraversal ist interner Iterator
 Markierung sichert auch Termination (falls Zyklen!)
alp3-9.3
 Markierung kann nach der Schleife wieder gelöscht
werden - dann aber Mehrfachbesuche (falls kein Baum)
Flexiblere Alternative:
depthFirstTraversal nicht als interner Iterator,
sondern als externer Algorithmus - typischerweise mit
Benutzung eines internen Iterators für das Durchlaufen
der Nachfolger eines Knotens:
public void iterate(Action a){
for(Node n: succ) a.act(n);
}
public interface Action {
void act(Node x);
}
alp3-9.3
4
class DepthFirst implements Node.Action {
public void act(Node n) {
traversal(n);
}
public void traversal(Node x){
if(!x.visited) {
x.visited = true;
x.iterate(this); }
}
}
Und damit new DepthFirst().traversal(start);
( visited muss public sein)
alp3-9.3
5
... und in Haskell: besuchte Ecken werden in Akkumulator memoriert
(keine Datenabstraktion):
graph = [ [...], [...], ..... ]
-- Liste von Adjazenzlisten
dft :: [Int]
->
-- Akkumulator
Anwendung:
Int
Ecke
-> [Int]
Erreichbare Ecken
dft [] root
dft list node -- erweitert list um alle
-- von node aus erreichbaren Ecken
| node `elem` list = list
-- und falls node noch nicht erfasst:
| otherwise
= foldl dft (node:list)
(graph!!node)
alp3-9.3
Zum Nacharbeiten: warum ist das korrekt?
6
9.3.2 Breitendurchlauf
Def.:
Breitendurchlauf von G ab w =
Breitendurchlauf von X(w) mit Ignorierung
von Unterbäumen mit bereits besuchter Wurzel,
typischerweise auch mit internem Iterator
Beispiel Breitensuche „nach roter Ecke“ (vgl. 6.4.4):
interface Predicate<X> { boolean holds(X x); }
breadthFirstSearch(Predicate<Node>()
{public boolean holds(Node p){
return p.colour=="red";}})
alp3-9.3
7
public Node breadthFirstSearch(Predicate<Node> p)
throws NotFound {
Queue<Node> q = new LinkedList<Node>();
q.add(this);
do{ Node n = q.remove();
if(p.holds(n)) return n;
n.visited = true;
for(Node succ: n.succ)
if(!succ.visited) q.add(succ); }
while(!q.isEmpty());
throw new NotFound();
}
alp3-9.3
8
9.3.3 Spannbäume
Def.:
Fluten eines Graphen:
Information wird von einem Startknoten
an alle (erreichbaren) Knoten weitergegeben
Das Fluten kann wahlweise mit Breiten*- oder Tiefendurchlauf
durchgeführt werden. Durch den Informationsfluss wird ein
Baum aufgespannt, der sogenannte
(Breiten- oder Tiefen-)Spannbaum (spanning tree)
*
alp3-9.3
In nichtsequentiellen Systemen - z.B. Rechnernetzen bietet sich Breitendurchlauf an!
9
b
a
d
c
a
a
b
d
d
b
c
Breiten-Spannbaum ab a
c
Tiefen-Spannbaum ab a
alp3-9.3
10
Fluten mit Tiefendurchlauf (9.3.1, S. 4/5, hier generisch):
class Flooding<T> implements Action<T> {
private T info;
public Flooding(T i) { info = i; }
public void act(Node<T> n) {
n.info = info;
flood(n);
}
public void flood(Node<T> x){
if(!x.visited) {
x.visited = true;
x.iterate(this); }
}
}
Und damit z.B.
new Flooding<String>("hi!").flood(start);
alp3-9.3
11
Def.:
Spannbaum S eines ungerichteten, gewichteten,
zusammenhängenden Graphen G:
freier Baum mit Kanten aus G und allen Ecken aus G
Def.:
minimaler Spannbaum S:
Spannbaum mit minimalen Kosten (d.h. Summe der
Kantengewichte)
Ein minimaler Spannbaum „dünnt die Kantenmenge des Graphen
so aus“, das eine möglichst große Kostenersparnis erzielt wird,
ohne dass der Graph zerfällt (9.5).
alp3-9.3
12
Herunterladen