• Keine Ergebnisse gefunden

Algorithmen und Datenstrukturen C3. Union-Find Gabriele R¨oger

N/A
N/A
Protected

Academic year: 2022

Aktie "Algorithmen und Datenstrukturen C3. Union-Find Gabriele R¨oger"

Copied!
37
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

C3. Union-Find

Gabriele R¨oger

Universit¨at Basel

(2)

Union-Find

(3)

Fragen

Sind die roten Knoten verbunden?

Wie viele Zusammenhangskomponenten hat der Graph?

(4)

Union-Find-Datentyp

K¨onnen Frage mit Hilfe folgendem Datentyp beantworten:

1 class UnionFind:

2 # Initialisiert n Knoten mit Namen 0, ..., n-1

3 def __init__(n: int) -> None

4

5 # F¨ugt Verbindung zwischen v und w hinzu

6 def union(v: int, w: int) -> None

7

8 # Komponentenbezeichner f¨ur v

9 def find(v: int) -> int

10

11 # Sind v und w verbunden?

12 def connected(v: int, w: int) -> bool

13

14 # Anzahl der Zusammenhangskomponenten

15 def count() -> int

(5)

(Etwas) naiver Algorithmus: Quick-Find

F¨urn Knoten: Arrayid der L¨angen Eintrag an Stelle i ist Bezeichner der

Zusammenhangskomponente, in der Knoten i liegt.

Anf¨anglich liegt jeder Knoten (alleine) in seiner eigenen Zusammenhangskomponente (insgesamtn St¨uck).

Aktualisiere das Array bei jedem Aufruf vonunion.

(6)

(Etwas) naiver Algorithmus: Quick-Find

F¨urn Knoten: Arrayid der L¨angen Eintrag an Stelle i ist Bezeichner der

Zusammenhangskomponente, in der Knoten i liegt.

Anf¨anglich liegt jeder Knoten (alleine) in seiner eigenen Zusammenhangskomponente (insgesamtn St¨uck).

Aktualisiere das Array bei jedem Aufruf vonunion.

(7)

(Etwas) naiver Algorithmus: Quick-Find

F¨urn Knoten: Arrayid der L¨angen Eintrag an Stelle i ist Bezeichner der

Zusammenhangskomponente, in der Knoten i liegt.

Anf¨anglich liegt jeder Knoten (alleine) in seiner eigenen Zusammenhangskomponente (insgesamtn St¨uck).

Aktualisiere das Array bei jedem Aufruf vonunion.

(8)

Quick-Find-Algorithmus

1 class QuickFind:

2 def __init__(self, no_nodes):

3 self.id = list(range(no_nodes))

4 self.components = no_nodes

5

6 def find(self, v):

7 return self.id[v]

8

9 def union(self, v, w):

10 id_v = self.find(v)

11 id_w = self.find(w)

12 if id_v == id_w: # already in same component

13 return

14 # replace all occurrences of id_v in self.id with id_w

15 for i in range(len(self.id)):

16 if self.id[i] == id_v:

17 self.id[i] = id_w

18 self.components -= 1 # we merged two components

[0, 1, ..., no nodes-1]

(9)

Quick-Find-Algorithmus (Fortsetzung)

20 def connected(self, v, w):

21 return self.find(v) == self.find(w)

22

23 def count(self):

24 return self.components

Aufwand?

Kostenmodell = Anzahl Arrayzugriffe ein Arrayzugriff f¨ur jeden Aufruf vonfind zwischen n+ 3 und 2n+ 1 Arrayzugriffe

f¨ur jeden Aufruf von union, der zwei Komponenten vereinigt

(10)

Etwas besserer Algorithmus: Quick-Union

(implizite) Baumstruktur zur Repr¨asentation jeder Zusammenhangskomponente

Repr¨asentiert durch Array mit Eintrag des Elternknotens (Wurzel: Referenz auf sich selbst)

0 1 2 3 4 5 6 7 8

3 5 0 3 6 5 3 6 5 3

6

4 7

0

2 5

8 1

Wurzelknoten dient als Bezeichner der Zusammenhangskomponente

(11)

Etwas besserer Algorithmus: Quick-Union

(implizite) Baumstruktur zur Repr¨asentation jeder Zusammenhangskomponente

Repr¨asentiert durch Array mit Eintrag des Elternknotens (Wurzel: Referenz auf sich selbst)

0 1 2 3 4 5 6 7 8

3 5 0 3 6 5 3 6 5 3

6

4 7

0

2 5

8 1

Wurzelknoten dient als Bezeichner der Zusammenhangskomponente

(12)

Quick-Union-Algorithmus

1 class QuickUnion:

2 def __init__(self, no_nodes):

3 self.parent = list(range(no_nodes))

4 self.components = no_nodes

5

6 def find(self, v):

7 while self.parent[v] != v:

8 v = self.parent[v]

9 return v

10

11 def union(self, v, w):

12 id_v = self.find(v)

13 id_w = self.find(w)

14 if id_v == id_w: # already in same component

15 return

16 self.parent[id_v] = id_w

17 self.components -= 1

18

19 # connected und count wie bei QuickFind

(13)

Erste Verbesserung

Problem bei Quick-Union: B¨aume k¨onnen zu Ketten entarten

→ find ben¨otigt lineare Zeit in der Gr¨osse der Komponente.

Idee: H¨ange inunion flacheren Baum an Wurzel Idee: des tieferen Baums

(14)

Ranked-Quick-Union-Algorithmus

1 class RankedQuickUnion:

2 def __init__(self, no_nodes):

3 self.parent = list(range(no_nodes))

4 self.components = no_nodes

5 self.rank = [0] * no_nodes # [0, ..., 0]

6

7 def union(self, v, w):

8 id_v = self.find(v)

9 id_w = self.find(w)

10 if id_v == id_w:

11 return

12 if self.rank[id_w] < self.rank[id_v]:

13 self.parent[id_w] = id_v

14 else:

15 self.parent[id_v] = id_w

16 if self.rank[id_v]== self.rank[id_w]:

17 self.rank[id_w] += 1

18 self.components -= 1

19

20 # connected, count und find wie bei QuickUnion

(15)

Zweite Verbesserung

Pfadkompression

Idee: H¨ange infind alle traversierten Knoten direkt an die Wurzel um

Wir aktualisieren die H¨ohe des Baumes bei der Pfadkompression nicht.

Wert vonrankkann von tats¨achlicher H¨ohe abweichen.

Deshalb heisst er auchRang(rank) statt H¨ohe.

(16)

Ranked-Quick-Union-Algorithmus mit Pfadkompression

1 class RankedQuickUnionWithPathCompression:

2 def __init__(self, no_nodes):

3 self.parent = list(range(no_nodes))

4 self.components = no_nodes

5 self.rank = [0] * no_nodes # [0, ..., 0]

6

7 def find(self, v):

8 if self.parent[v] == v:

9 return v

10 root = self.find(self.parent[v])

11 self.parent[v] = root

12 return root

13

14 # connected, count und union wie bei RankedQuickUnion

(17)

Diskussion

Mit allen Verbesserungen erreichen wir beinahe konstante amortisierte Kosten f¨ur alle Operationen

Genauer: [Tarjan 1975]

mAufrufe vonfind beinObjekten (und h¨ochstensn1 Aufrufe vonunion, die zwei Komponenten vereinigen) O(mα(m,n)) Arrayzugriffe

αist Umkehrfunktion einer Variante der Ackermann-Funktion In der Praxis istα(m,n)3.

Trotzdem: es kann keinen Union-Find-Algorithmus geben, der lineare Zeit garantieren kann.

(unter

Cell-Probe“-Berechnungsmodell)

(18)

Diskussion

Mit allen Verbesserungen erreichen wir beinahe konstante amortisierte Kosten f¨ur alle Operationen

Genauer: [Tarjan 1975]

mAufrufe vonfind beinObjekten (und h¨ochstensn1 Aufrufe vonunion, die zwei Komponenten vereinigen) O(mα(m,n))Arrayzugriffe

αist Umkehrfunktion einer Variante derAckermann-Funktion In der Praxis istα(m,n)3.

Trotzdem: es kann keinen Union-Find-Algorithmus geben, der lineare Zeit garantieren kann.

(unter

Cell-Probe“-Berechnungsmodell)

(19)

Diskussion

Mit allen Verbesserungen erreichen wir beinahe konstante amortisierte Kosten f¨ur alle Operationen

Genauer: [Tarjan 1975]

mAufrufe vonfind beinObjekten (und h¨ochstensn1 Aufrufe vonunion, die zwei Komponenten vereinigen) O(mα(m,n))Arrayzugriffe

αist Umkehrfunktion einer Variante derAckermann-Funktion In der Praxis istα(m,n)3.

Trotzdem: es kann keinen Union-Find-Algorithmus geben, der lineare Zeit garantieren kann.

(unter

Cell-Probe“-Berechnungsmodell)

(20)

Vergleich mit explorationsbasiertem Verfahren

Kapitel C2: Algorithmus ConnectedComponents, der auf Graphenexplorationbasiert

Nach der Vorberechnung kosten Anfragen nur konstante Zeit.

In der Praxis ist Union-Find meist schneller, da der Graph f¨ur viele Zwecke nicht vollst¨andig aufgebaut werden muss.

Ist der Graph schon aufgebaut, kann Graphenexploration besser sein.

Weiterer Vorteil von Union-Find Online-Verfahren

problemloses Hinzuf¨ugen weiterer Kanten

(21)

Zusammenhangskomponenten und

Aquivalenzklassen ¨

(22)

Wiederholung: Zusammenhangskomponenten

UngerichteterGraph

Zwei Knoten u und v sind genau dann in der gleichen Zusammenhangskomponente, wenn es einen Pfad

zwischen u und v gibt (= Knotenu und v verbundensind).

0 1

2 3

4

5

6

7 8

9

(23)

Zusammenhangskomponenten: Eigenschaften

Die Zusammenhangskomponenten definieren eine Partition der Knoten:

Jeder Knoten ist in einer Zusammenhangskomponente.

Kein Knoten ist in mehr als einer Zusammenhangskomponente.

”ist verbunden mit“ ist Aquivalenzrelation¨

reflexiv:Jeder Knoten ist mit sich selbst verbunden.

symmetrisch:Ist umitv verbunden, dann istv mitu verbunden.

transitiv:Istumitv verbunden undv mitw verbunden, dann istumitw verbunden.

(24)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Partition allgemein

Definition (Partition)

EinePartition einer endlichen Menge M ist eine Menge P nicht-leerer Teilmengen vonM, so dass

jedes Element von M in einer Menge in P vorkommt:

S

S∈PS =M, und

die Mengen in P paarweise disjunkt sind:

S∩S0=∅f¨ur S,S0 ∈P mitS 6=S0. Die Mengen inP heissen Bl¨ocke.

M ={e1, . . . ,e5}

P1={{e1,e4},{e3},{e2,e5}}

P2={{e1,e4,e5},{e3}}

ist keine Partition vonM.

P3={{e1,e4,e5},{e3},{e2,e5}}

ist keine Partition von M.

P4={{e1},{e2},{e3},{e4},{e5}}

ist eine Partition von M.

(25)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Partition allgemein

Definition (Partition)

EinePartition einer endlichen Menge M ist eine Menge P nicht-leerer Teilmengen vonM, so dass

jedes Element von M in einer Menge in P vorkommt:

S

S∈PS =M, und

die Mengen in P paarweise disjunkt sind:

S∩S0=∅f¨ur S,S0 ∈P mitS 6=S0. Die Mengen inP heissen Bl¨ocke.

M ={e1, . . . ,e5}

P1={{e1,e4},{e3},{e2,e5}}ist eine Partition von M.

P2={{e1,e4,e5},{e3}}

P3={{e1,e4,e5},{e3},{e2,e5}}

ist keine Partition von M.

P4={{e1},{e2},{e3},{e4},{e5}}

ist eine Partition von M.

(26)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Partition allgemein

Definition (Partition)

EinePartition einer endlichen Menge M ist eine Menge P nicht-leerer Teilmengen vonM, so dass

jedes Element von M in einer Menge in P vorkommt:

S

S∈PS =M, und

die Mengen in P paarweise disjunkt sind:

S∩S0=∅f¨ur S,S0 ∈P mitS 6=S0. Die Mengen inP heissen Bl¨ocke.

M ={e1, . . . ,e5}

P1={{e1,e4},{e3},{e2,e5}}ist eine Partition von M.

P2={{e1,e4,e5},{e3}}ist keine Partition von M. P3={{e1,e4,e5},{e3},{e2,e5}}

P4={{e1},{e2},{e3},{e4},{e5}}

ist eine Partition von M.

(27)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Partition allgemein

Definition (Partition)

EinePartition einer endlichen Menge M ist eine Menge P nicht-leerer Teilmengen vonM, so dass

jedes Element von M in einer Menge in P vorkommt:

S

S∈PS =M, und

die Mengen in P paarweise disjunkt sind:

S∩S0=∅f¨ur S,S0 ∈P mitS 6=S0. Die Mengen inP heissen Bl¨ocke.

M ={e1, . . . ,e5}

P1={{e1,e4},{e3},{e2,e5}}ist eine Partition von M.

P2={{e1,e4,e5},{e3}}ist keine Partition von M.

P3={{e1,e4,e5},{e3},{e2,e5}} ist keine Partition von M. P4={{e1},{e2},{e3},{e4},{e5}}

(28)

Partition allgemein

Definition (Partition)

EinePartition einer endlichen Menge M ist eine Menge P nicht-leerer Teilmengen vonM, so dass

jedes Element von M in einer Menge in P vorkommt:

S

S∈PS =M, und

die Mengen in P paarweise disjunkt sind:

S∩S0=∅f¨ur S,S0 ∈P mitS 6=S0. Die Mengen inP heissen Bl¨ocke.

M ={e1, . . . ,e5}

P1={{e1,e4},{e3},{e2,e5}}ist eine Partition von M.

P2={{e1,e4,e5},{e3}}ist keine Partition von M.

P3={{e1,e4,e5},{e3},{e2,e5}} ist keine Partition von M. P4={{e1},{e2},{e3},{e4},{e5}} ist eine Partition vonM.

(29)

Aquivalenzrelation allgemein ¨

Definition (¨Aquivalenzrelation)

EineAquivalenzrelation¨ auf einer MengeM ist eine

symmetrische, transitive und reflexiveRelationR ⊆M×M.

Wir schreibena∼b f¨ur (a,b)∈R und sagenaist ¨aquivalent zub.

symmetrisch: a∼b impliziertb ∼a transitiv: a∼b und b∼c implizierta∼c reflexiv: f¨ur alle e ∈M:e ∼e

(30)

Aquivalenzklassen ¨

Definition (¨Aquivalenzklassen)

SeiR eine ¨Aquivalenzrelation auf der Menge M. DieAquivalenzklasse¨ von a∈M ist die Menge

[a] ={b∈M |a∼b}.

Die Menge aller ¨Aquivalenzklassen ist eine Partition vonM. Umgekehrt:

F¨ur PartitionP definiere R={(x,y)| ∃B∈P :x,y∈B}

(alsox ∼y genau dann, wennx und y im gleichen Block).

Dann ist R eine ¨Aquivalenzrelation.

K¨onnen Partitionen als ¨Aquivalenzklassen betrachten und umgekehrt.

(31)

Aquivalenzklassen ¨

Definition (¨Aquivalenzklassen)

SeiR eine ¨Aquivalenzrelation auf der Menge M. DieAquivalenzklasse¨ von a∈M ist die Menge

[a] ={b∈M |a∼b}.

Die Menge aller ¨Aquivalenzklassen ist eine Partition vonM. Umgekehrt:

F¨ur PartitionP definiere R={(x,y)| ∃B∈P :x,y∈B}

(alsox ∼y genau dann, wennx und y im gleichen Block).

Dann ist R eine ¨Aquivalenzrelation.

K¨onnen Partitionen als ¨Aquivalenzklassen betrachten und umgekehrt.

(32)

Aquivalenzklassen ¨

Definition (¨Aquivalenzklassen)

SeiR eine ¨Aquivalenzrelation auf der Menge M. DieAquivalenzklasse¨ von a∈M ist die Menge

[a] ={b∈M |a∼b}.

Die Menge aller ¨Aquivalenzklassen ist eine Partition vonM. Umgekehrt:

F¨ur PartitionP definiere R={(x,y)| ∃B∈P :x,y∈B}

(alsox ∼y genau dann, wennx und y im gleichen Block).

Dann ist R eine ¨Aquivalenzrelation.

K¨onnen Partitionen als ¨Aquivalenzklassen betrachten und umgekehrt.

(33)

Aquivalenzklassen ¨

Definition (¨Aquivalenzklassen)

SeiR eine ¨Aquivalenzrelation auf der Menge M. DieAquivalenzklasse¨ von a∈M ist die Menge

[a] ={b∈M |a∼b}.

Die Menge aller ¨Aquivalenzklassen ist eine Partition vonM. Umgekehrt:

F¨ur PartitionP definiere R={(x,y)| ∃B∈P :x,y∈B}

(alsox ∼y genau dann, wennx und y im gleichen Block).

Dann ist R eine ¨Aquivalenzrelation.

K¨onnen Partitionen als ¨Aquivalenzklassen betrachten und umgekehrt.

(34)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Union-Find und ¨ Aquivalenzen

Gegeben: endliche MengeM,

Sequenz s von ¨Aquivalenzen a∼b ¨uberM Fasse ¨Aquivalenzen als Kanten in Graphen mit Knotenmenge M auf.

Die Zusammenhangskomponenten entsprechen den Aquivalenzklassen der feinsten ¨¨ Aquivalenzrelation, die alle ¨Aquivalenzen auss enth¨alt.

keine

unn¨otigen“ ¨Aquivalenzen

Bestimmung der ¨Aquivalenzklassen verwenden.

(35)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Union-Find und ¨ Aquivalenzen

Gegeben: endliche MengeM,

Sequenz s von ¨Aquivalenzen a∼b ¨uberM Fasse ¨Aquivalenzen als Kanten in Graphen mit Knotenmenge M auf.

Die Zusammenhangskomponenten entsprechen den Aquivalenzklassen der feinsten ¨¨ Aquivalenzrelation, die alle ¨Aquivalenzen auss enth¨alt.

keine

unn¨otigen“ ¨Aquivalenzen

Bestimmung der ¨Aquivalenzklassen verwenden.

(36)

Union-Find Zusammenhangskomponenten und ¨Aquivalenzklassen

Union-Find und ¨ Aquivalenzen

Gegeben: endliche MengeM,

Sequenz s von ¨Aquivalenzen a∼b ¨uberM Fasse ¨Aquivalenzen als Kanten in Graphen mit Knotenmenge M auf.

Die Zusammenhangskomponenten entsprechen den Aquivalenzklassen der¨ feinsten ¨Aquivalenzrelation, die alle ¨Aquivalenzen auss enth¨alt.

keine

unn¨otigen“ ¨Aquivalenzen

Bestimmung der ¨Aquivalenzklassen verwenden.

(37)

Union-Find und ¨ Aquivalenzen

Gegeben: endliche MengeM,

Sequenz s von ¨Aquivalenzen a∼b ¨uberM Fasse ¨Aquivalenzen als Kanten in Graphen mit Knotenmenge M auf.

Die Zusammenhangskomponenten entsprechen den Aquivalenzklassen der¨ feinsten ¨Aquivalenzrelation, die alle ¨Aquivalenzen auss enth¨alt.

keine

unn¨otigen“ ¨Aquivalenzen Wir k¨onnen dieUnion-Find-Datenstruktur zur Bestimmung der ¨Aquivalenzklassenverwenden.

Referenzen

ÄHNLICHE DOKUMENTE

Elemente werden in Array gespeichert, wobei Position durch Schl¨ ussel bestimmt ist.. Wichtigstes Werkzeug: Hashfunktion Berechnet Index aus

In einer auf Verkettung basierenden Hashtabelle mit M Listen und N Schl¨ usseln ist die Anzahl der Vergleiche (Gleichheitstests) f¨ ur Einf¨ ugungen und erfolglose Suchen ∼

G ist stark zusammenh¨ angend, wenn von jedem Knoten zu jedem anderen Knoten ein gerichteter Pfad existiert. Eine starke Zusammenhangskomponente von G ist ein maximal grosser

I In der Praxis ist Union-Find meist schneller, da der Graph f¨ ur viele Zwecke nicht vollst¨ andig aufgebaut werden muss. I Ist der Graph schon aufgebaut, kann

I distance[u]: L¨ ange des k¨ urzesten bekannten Pfades zu u I distance[v]: L¨ ange des k¨ urzesten bekannten Pfades zu v I parent[v]: Vorg¨ anger in letzter Kante. des k¨

distance: knotenindiziertes Array, das an Stelle v die Kosten des k¨ urzesten bekannten Pfades vom Startknoten zu v enth¨ alt.. pq: indizierte Priority-Queue von Knoten Knoten

I Liegt ein Knoten eines solchen Zyklus auf einem Pfad von s nach v, k¨ onnen wir Pfade finden, deren Gewicht niedriger als jeder gegebene Wert ist. → kein korrekt

Bestimmte Grundbausteine ben¨ otigt man immer wieder bei Programmierprojekten, z.B. Sortierverfahren