COMP 261 Lecture 12

COMP 261 Lecture 12
Disjoint Sets
Kruskal's Algorithm
7
5
B
A
3
2
I
6
D
9
4
10
1
C
1
17
H
6
8
10
E
3
J
14
G
4
25
18
23
F
• Questions:
– How to find the smallest edge efficiently?
– How to efficiently determine if an edge connects two trees or not?
Refining Kruskal's algorithm
• Given: a graph with N nodes and E weighted edges
forest ← a set of N sets of nodes, each containing one node of the graph
edges ← a priority queue of all the edges: 〈n1, n2, length〉 priority:
short edges first
spanningTree ← an empty set of edges
Repeat until forest contains only one tree or edges is empty:
〈n1, n2, length〉 ← dequeue(edges)
If n1 and n2 are in different sets in forest then
merge the two sets in forest
What's the
Add edge to the spanningTree
cost?
return spanningTree
• Implementing forest :
– set of sets with two operations:
• findSet(n1) =?= findSet(n2)
= "find" the set that n is in
• merge(s1, s2)
= replace s1, s2 by their "union"
Implementing sets of sets
1: forest = set of sets of nodes:
– findSet(n1)
• iterate through all sets, calling s.contains(n1)
– merge (s1 , s2)
• add each element of s1 to s2 and remove s1
– cost?
A
F
H
B
C
E
D
G
J
I
Implementing sets of sets
2: forest = mark each node with ID of its set
– findSet(n1):
• look up n1.setID
– merge(s1 , s2)
• iterate through all nodes, changing IDs of nodes in s1
– cost?
A
1
B
2
C
2
D
3
E
2
F
1
G
3
H
1
I
1
J
3
Union–Find structure
3: forest: set of inverted trees of nodes:
• Each set represented by a linked tree with links pointing
towards the root
Z
A
T
C
G
X
J
D
E
U
S
R
K
R
Y
Q
W
H
N
• The nodes in these trees are the nodes of the graph
Union–Find structure
MakeSet(x):
x.parent ← x
add x to set
Find(A) = A
Find(G) = A
Find(E) = A
Find(W) = A
…
Z
A
Find(x)
if x.parent = x
Recursively go
return x
up to the root
else
root ← Find(x.parent)
return root
T
C
G
E
R
Q
W
Union–Find structure
Union(x, y):
xroot ← Find(x)
yroot ← Find(y)
if xroot = yroot
return
else
xroot.parent ← yroot
remove xroot from set.
Union(E,T)
A
G
xroot
yroot
T
C
E
R
y
x
Q
W
Union–Find structure
Union(x, y):
xroot ← Find(x)
yroot ← Find(y)
if xroot = yroot
return
else
xroot.parent ← yroot
remove xroot from set.
Union(x,y) = Union(y,x)?
Union(E,U)
J
A
xroot
U
G
T
C
E
R
yroot
K
x
Q
W
y
Union–Find structure
Union(x, y):
xroot ← Find(x)
yroot ← Find(y)
if xroot = yroot
return
else
xroot.parent ← yroot
remove xroot from set.
Union(U,E)
J
A
yroot
U
G
T
C
E
R
xroot
x
K
y
Q
W
Union(x,y) = Union(y,x)?
• Order will affect tree depth (search complexity)
Union–Find structure
• find(Q), union(E, Z), union(H, K), union(Y, G)
Z
A
C
G
X
T
J
D
E
U
S
R
K
R
Y
Q
W
H
N
• Problem: the trees can get unreasonably long
• Solutions: shorten the trees; add shorter trees to longer
Union–Find: Better
MakeSet(x):
x.parent ← x
add x to set
x.depth ← 0
Union(x, y)
keeping track of
depth lets us add
the smaller tree
to the larger tree
Find(x)
if x.parent = x Modify tree to
keep paths short
return x
else
root ← Find(x.parent)
return root
Amortised
cost < 5!
xroot ← Find(x)
yroot ← Find(y)
if xroot = yroot then return
if xroot.depth < yroot.depth
xroot.parent ← yroot
remove xroot from set
else
yroot.parent ← xroot
remove yroot from set
if xroot.depth = yroot.depth
xroot.depth ++
Union–Find structure
• find(Q), union(E, Z), union(H, K), union(Y, G)
Z0
A4
T0
C3
G0
E2
R0
X3
J2
D2
S0
U1
K0
R1
Y1
Q1
W0
H0
N0
Applications
• Union-Find is very efficient for a collection of sets if
– All sets are disjoint.
– Only asking for same set membership and merging
two sets.
• Inefficient for
– enumerating the elements of a set
– removing an element from a set
• Doesn't work if the sets could share elements
Exercise:
B
18
1
A
12
11
7
14
13
8
B
C
D
3
E
17
J
19
15
20
F
G
A
16
9
I
H
D
6
5
10
4
C
2
E
F
G
H
I
J