SlideShare a Scribd company logo
CICS 210
Data Structures
Union-Find
V1 - 11/24/2024
MJ Golin
CICS Fall 2024
2
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
3
The Union Find Problem
• We’re now returning to graph connectivity.
• Will see an algorithm for being able to answer graph connectivity updates quickly.
• This will actually be an algorithm for set maintenance (under insertions).
1
9 3
5
4 8
7
6
11
10
2
12
13
Recall graph connectivity (undirected graphs).
• Two vertices in a graph are connected
if there exists a path from one to the other.
• A connected component is a maximal
subgraph in which every vertex is connected
to every other vertex.
Graph to the left has 3 connected components.
4
The Union Find Problem
• We’re now returning to graph connectivity
• Will see an algorithm for being able to answer graph connectivity updates quickly
• This will actually be an algorithm for set maintenance (under insertions)
1
9 3
5
4 8
7
6
11
10
2
12
13
Connected(a,b): query that returns true if and only
if a and b are in the same connected component.
A B C
Find(a): query that returns the name of the
component containing a.
Find(3) = Find(6) = A; Find(2) = C
5
The Union Find Problem
Note that Connected(a,b) is only asking whether a,b are in the same connected component set.
A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing
We stated this “connected” problem in a graph but
remember, graphs model relationships. So this
problem can be applied to anything that can be
modeled by a relationship graph, e.g.,
• Pixels in a digital photo.
• Computers in a network.
• Friends in a social network.
• Transistors in a computer chip.
• Elements in a mathematical set.
• Variable types in a program.
We should also point out that connected components in graphs model “equivalence
relations”. So we’re really trying to figure out if two item are equivalent to each other in an
equivalence relation.
1
9 3
5
4 8
7
6
11
10
2
12
13
6
The Union Find Problem
Suppose that we start with no edges.
The problem is to add edges and keep track of them in such a way that we can always
answer Connected(a,b) efficiently. Union (a,b) will denote adding the edge (a,b).
1
9 3
5
4 8
7
6
Connected(4,7)?
Union(4,9)
𝐹𝑎𝑙𝑠𝑒
𝑇𝑟𝑢𝑒
Union(3,5)
Connected(4,8)? 𝐹𝑎𝑙𝑠𝑒
Union(3,8)
Connected(5,8)?
Connected(1,4)? 𝐹𝑎𝑙𝑠𝑒
Union(1,9)
Union(9,5)
Connected(4,8)? 𝑇𝑟𝑢𝑒
Union(1,3)
7
The Union Find Problem
Note that Connected(a,b) is only asking whether a,b are in the same connected component set.
A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing
1
9 3
5
4 8
7
6
Connected(4,7)?
Union(4,9)
𝐹𝑎𝑙𝑠𝑒
𝑇𝑟𝑢𝑒
Union(3,5)
Connected(4,8)? 𝐹𝑎𝑙𝑠𝑒
Union(3,8)
Connected(5,8)?
Connected(1,4)? 𝐹𝑎𝑙𝑠𝑒
Union(1,9)
Union(9,5)
Connected(4,8)? 𝑇𝑟𝑢𝑒
Union(1,3)
1 3 {4} 5 6 7 8 {9}
1 3 {4,9} 5 6 7 8
1 3,5 {4,9} 6 7 8
1 3,5,8 {4,9} 6 7
3,5,8 {1,4,9} 6 7
1,3,5,8,4,9 6 7
No Change!
8
The Union Find Problem
Note that Connected(a,b) is only asking whether a,b are in the same connected component set.
A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing
1
9 3
5
4 8
7
6
We know how to find connected components in time linear in
𝑂(𝑉 + 𝐸) but we don’t want to have to redo the entire
algorithm every time we change the graph by adding an edge.
We’re now going to develop an algorithm for doing this more
efficiently. Our algorithm will be for set maintenance.
9
The Union Find Problem
Assume that out items (vertices) are integers on [0, 𝑛 − 1]
Want to support
• union(p, q) - add an edge between p and q, placing them into the same connected component
• find(p) - return the component id (an int) for the vertex p
• connected(p, q) - true if and only if p and q are in the same component
Every item will have an (integer) id that is the name of the component it belongs.
Since connected(p, q) == (find(p) == find(q))
it is unnecessary to derive it further
public interface UnionFind {
int find(int p);
void union(int p, int q);
boolean connected(int p, int q);
}
10
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
11
First Simple Version
1
2 3
5
4 0
𝑖 0 1 2 3 4 5
𝑖𝑑[𝑖] 0 1 1 0 2 1
• union(p, q) – change all
entries whose id equals 𝑖𝑑[𝑝]
to 𝑖𝑑[𝑞]
• find(p) – return 𝑖𝑑[𝑝]
union(2, 0)
1
2 3
5
4 0
𝑖 0 1 2 3 4 5
𝑖𝑑[𝑖] 0 0 0 0 2 0
12
public class QuickFindUF implements UnionFind {
private int[] id;
public QuickFindUF(int N) {
id = new int[N];
for (int i = 0; i < N; i++) {
id[i] = i; // each in own component to start
}
}
public int find(int p) {
return id[p];
}
public void union(int p, int q) {
int pid = id[p];
int qid = id[q];
for (int i = 0; i < id.length; i++) {
if (id[i] == pid) {
id[i] = qid;
}
}
}
public boolean connected(int p, int q) {
return find(p) == find(q);
}
}
Initialize by having every item in its
own component (setting id[i]=i)
find(p) just returns p’s ID
union(p,q) sets the id of
everyone in same set as p to id[q]
connected(p,q) returns whether
p and q are in the same set
13
First Simple Version
1
2 3
5
4 0
𝑖 0 1 2 3 4 5
𝑖𝑑[𝑖] 0 1 1 0 2 1
• union(p, q) – change all entries
whose id equals 𝑖𝑑[𝑝] to 𝑖𝑑[𝑞]
• find(p) – return 𝑖𝑑[𝑝]
union(2, 0)
1
2 3
5
4 0
𝑖 0 1 2 3 4 5
𝑖𝑑[𝑖] 0 0 0 0 2 0
Bad running time.
Can take 𝑂 𝑉 time per step
Sequence
union(0,1)
union(1,2)
union(2,3)
…
union(n-2,n-1)
would take Θ 𝑛2
time.
14
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
15
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝.
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
The highest item in an up-tree is its root.
The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
0
1
2 3
4
5
6 7
8
9
• Items are decomposed into trees.
• 𝑖𝑑[𝑖] is parent of 𝑖 in its tree
• root 𝑖 is identified by 𝑖𝑑 𝑖 = 𝑖
16
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝.
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
The highest item in an up-tree is its root.
The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the
up-tree containing 𝑝.
Example:
𝑓𝑖𝑛𝑑 7 = 𝑓𝑖𝑛𝑑 2 = 𝑓𝑖𝑛𝑑 9 = 9
𝑓𝑖𝑛𝑑 0 = 𝑓𝑖𝑛𝑑 3 = 3
𝑓𝑖𝑛𝑑 5 = 5
0
1
2 3
4
5
6 7
8
9
17
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝.
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
The highest item in an up-tree is its root.
The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
union(p, q) – if 𝑝 and 𝑞 are in different sets, merge
the sets by setting the id of the root of the up-tree
containing 𝑝 to be the root of the up-tree containing 𝑞
i.e., 𝑖𝑑 𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞).
0
1
2 3
4
5
6 7
8
9
Example: 𝑢𝑛𝑖𝑜𝑛(0,1)
X
X
9
Sets 𝑖𝑑 3 = 𝑓𝑖𝑛𝑑 1 = 9
18
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
19
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 1 2 3 4 5 6 7 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝.
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝.
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑 𝑝 = 𝑓𝑖𝑛𝑑 𝑞 .
0 1 2 3 4 5 6 7 8 9
20
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 1 2 3 4 5 6 7 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1 2 3 4 5 6 7 8 9
Union(1,2)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
21
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 7 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6 7 8 9
Union(1,2) Now Find(1)=Find(2)=2
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
22
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 7 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6 7 8 9
Union(7,2)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
23
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7 8 9
Union(7,2) Now Find(1)=Find(2)=Find(7)=2
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
24
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 8 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7 8 9
Union(8,9)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
25
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7 8
9
Union(8,9) Now Find(8)=Find(9)=9
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
26
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7 8
9
Union(7,8) This will set 𝑖𝑑 𝑓𝑖𝑛𝑑 7 = 𝑖𝑑 𝑓𝑖𝑛𝑑 8
𝑖𝑑 2 = 𝑖𝑑 9 = 9
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
27
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 9 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7
8
9
Union(7,8)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
28
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 9 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0 1
2
3 4 5 6
7
8
9
Union(0,3)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
29
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4 5 6
7
8
9
Union(0,3)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
30
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4 5 6
7
8
9
Union(8,2) Since Find(8)=Find(2)=9 this does nothing
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
31
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4 5 6
7
8
9
Union(4,7) Sets id[4]=Find(7)=9
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
32
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4
5 6
7
8
9
Union(4,7) Sets id[4]=Find(7)=9
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
33
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4
5 6
7
8
9
Union(1,4) Since Find(1)=Find(4)=9 this does nothing
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
34
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4
5 6
7
8
9
Union(0,5)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
35
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4
5
6
7
8
9
Union(0,5)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
36
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 9
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2 3
4
5
6
7
8
9
Union(7,6)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
37
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 6
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2
3
4
5
6
7
8
9
Union(7,6)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
38
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 6
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2
3
4
5
6
7
8
9
Union(2,0)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
39
2nd version: Up trees
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 3 2 9 5 9 5 5 2 9 6
7
6
8
9
Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝
Sets (items in the same component) will be represented
by up-trees. Every item will start in its component, with
𝑖𝑑 𝑝 = 𝑝.
In the general scenario, the items in a component will
be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of
another item in the same set “above it” in the up-tree.
0
1
2
3
4
5
6
7
8
9
Union(2,0)
• find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of
the up-tree containing 𝑝
• union(p, q) – if 𝑝 and 𝑞 are in different sets,
merge the sets by setting the id of the root of
the up-tree containing 𝑝 to be the root of the
up-tree containing 𝑞
i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞)
The highest item in an up-tree is its root. The root 𝑖 of the
up-tree has 𝑖𝑑 𝑖 = 𝑖;
40
public class QuickUnion implements UnionFind {
private int[] id;
public QuickUnion(int N) {
id = new int[N];
for (int i = 0; i < N; i++) {
id[i] = i; // each in own component to start
}
}
public int find(int p) {
while (p != id[p]) {
p = id[p];
}
return p;
}
public void union(int p, int q) {
id[find(p)] = find(q);
}
public boolean connected(int p, int q) {
return find(p) == find(q);
}
}
Same as before
Returns the root of the tree that contains p.
Does this by walking up parents in tree until it finds
the root, which is the node satisfying 𝑖 = 𝑖𝑑 𝑖 .
union(p,q) points root of tree containing p to root of
tree containing q.
Note: If find[p]=find[q] it points root to itself, not
changing anything.
41
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
42
3rd version: Up trees with Union by size
Suppose we did
union(0,1)
union(0,2)
union(0,3)
…
union(0,n-1)
What would happen?
0
1
0
1
2
0
1
2
3
0
1
2
3
𝑛 − 2
n − 1
How much time would this require?
After the first 𝑖 unions, it takes 𝑖 − 1 steps to implement 𝑓𝑖𝑛𝑑 0 , so total work is σ𝑖=1
𝑛−1
𝑖 − 1 = Θ(𝑛2)
The problem is that the trees built are long and narrow.
Can you see a way to fix this?
43
3rd version: Union by size
The problem was that we made the root of a small tree (one node) the parent of the larger tree.
One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree.
As an example, consider this scenario we saw earlier
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9
7
6
8
9
0 1
2
3 4 5 6
7 8
9
As an example, consider this scenario we saw earlier
We were asked to do Union(7,8) so we pointed 2 to 9
Since we are doing Union by size, we would point 9 to 2 instead.
44
3rd version: Union by size
The problem was that we made the root of a small tree (one node) the parent of the larger tree.
One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree.
As an example, consider this scenario we saw earlier
1
2 3
5
4
0
𝑖 0 1 2 3 4 5 6 7 8 9
𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 2
7
6
8
9
0 1
2
3 4 5 6
7
8
9
As an example, consider this scenario we saw earlier
We were asked to do Union(7,8) so we pointed 2 to 9
Since we are doing Union by size, we would point 9 to 2 instead.
45
3rd version: Union by size (Implementation)
The problem was that we made the root of a small tree (one node) the parent of the larger tree.
One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree.
For each node: Also keep a size variable sz[i].
sz[i] will be the number of nodes in the tree rooted at i (only used if 𝑖 is the root of its up-tree)
public void union(int p, int q) {
int i = find(p);
int j = find(q);
if (i == j) return;
if (sz[i] < sz[j]) {
id[i] = j;
sz[j] += sz[i];
} else {
id[j] = i;
sz[i] += sz[j];
}
}
i, j are the roots of the two trees
If tree rooted at i is larger, make i the root
Otherwise, make j the root the roots of the two trees
In both cases update the size of the root of the combined tree to reflect
thatit now contains everything
46
3rd version: Up trees with Union by size
Suppose we now redo our quadratic bad case using union by size
union(0,1)
union(0,2)
union(0,3)
…
union(0,n-1)
Then we would get
0
1
0
1
2 3 0 2 3
𝑛 − 2 n − 1
This only takes 𝑂 1 time per step.
We’ll now see that, when using union by size, the trees never get higher than log2 𝑛, so no
find or union step requires more than 𝑂(log 𝑛) time.
0
1
2 …
47
3rd version: Up trees with Union by size
Theorem: For any 𝑥 let 𝑑 𝑥 be the depth of 𝑥 in its up-tree and 𝑠𝑖𝑧𝑒(𝑥) the #
of nodes in its up-tree. Then 2𝑑(𝑥)
≤ 𝑠𝑖𝑧𝑒 𝑥 .
Let 𝑛 be the total # of nodes.
This means that every union and find operation takes 𝑂(log 𝑛) time
Assume theorem is true
Since, for every 𝑥, 2𝑑(𝑥)
≤ 𝑠𝑖𝑧𝑒 𝑥 ≤ 𝑛,
we get 𝑑 𝑥 ≤ log2 𝑛 ,
which means that 𝑓𝑖𝑛𝑑(𝑥) never takes more than log2 𝑛 steps.
In particular, 𝑛 operations takes 𝑂 𝑛 𝑙𝑜𝑔 𝑛 time, a big improvement from
the 𝑂(𝑛2
) of the previous version.
48
3rd version: Up trees with Union by size
• At start, for every node 𝑥, 𝑑(𝑥) = 0 and 𝑠𝑖𝑧𝑒 𝑥 = 1, so 2𝑑(𝑥) = 1 = 𝑠𝑖𝑧𝑒 𝑥 .
• Since 𝑑 𝑥 ≤ 𝑑′(𝑥) and 𝑠𝑖𝑧𝑒 𝑥 ≤ 𝑠𝑖𝑧𝑒′ 𝑥 , this can only be violated if 𝑑′ 𝑥 > 𝑑 𝑥 .
Without loss of generality assume that 𝑓𝑖𝑛𝑑 𝑥 = 𝑓𝑖𝑛𝑑(𝑝)
𝑑′ 𝑥 > 𝑑 𝑥 can only happen if 𝑓𝑖𝑛𝑑(𝑞) becomes the parent of 𝑓𝑖𝑛𝑑(𝑝).
Proof: Consider any union(𝑝, 𝑞) step (only time at which values changes).
Let 𝑑 𝑥 , 𝑠𝑖𝑧𝑒(𝑥) be the values before the union and 𝑑′ 𝑥 , 𝑠𝑖𝑧𝑒′(𝑥) the values after the union.
For all 𝑥, assume that (∗) is satisfied before the union.
We want to show that 2𝑑′ 𝑥 ≤ 𝑠𝑖𝑧𝑒′(𝑥) afterwards as well.
⇒ 2𝑑(𝑥) ≤ 𝑠𝑖𝑧𝑒 𝑥 = 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 ≤ 𝑠𝑖𝑧𝑒(𝑓𝑖𝑛𝑑 𝑞 )
⇒ 𝑑′(𝑥) = 𝑑 𝑥 + 1; 𝑠𝑖𝑧𝑒′ 𝑥 = 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑(𝑥) + 𝑠𝑖𝑧𝑒(𝑓𝑖𝑛𝑑(𝑞))
⇒ 2𝑑′(𝑥) = 2 ⋅ 2𝑑 𝑥 ≤ 2 ⋅ 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 ≤ 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 + 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑞 = 𝑠𝑖𝑧𝑒′(𝑥)!
Theorem: For any 𝑥 let 𝑑 𝑥 be the depth of 𝑥 in its up-tree and 𝑠𝑖𝑧𝑒(𝑥) the # of nodes in its
up-tree. Then ∗ 2𝑑(𝑥)
≤ 𝑠𝑖𝑧𝑒 𝑥 .
𝑝 𝑞
𝑓𝑖𝑛𝑑(𝑝)
𝑓𝑖𝑛𝑑(𝑞)
𝑠𝑖𝑧𝑒 𝑝 ≤ 𝑠𝑖𝑧𝑒(𝑞)
𝑥
49
Outline
• Union Find
• Introduction
• First version
• Up-trees
• Union by size
• Going further
50
4th version: Adding path compression
The running time can be improved via another trick.
In find(x), first trace the path from 𝑥 to the root.
Let 𝑟 be the root of the tree, and the path from 𝑥 to 𝑟 be 𝑥𝑎1𝑎2 … 𝑎𝑘𝑟.
Run through the path again, this time setting all the id’s (parent pointers) of
𝑥, 𝑎1, 𝑎2 , … , 𝑎𝑘 to be the root 𝑟 .
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
X
X
X
This is called Path compression.
It requires 𝑓𝑖𝑛𝑑(𝑥) to make two
loops. The first to find 𝑟; the
second to walk up from 𝑥 again,
changing all of the id’s.
This will make the trees very
shallow!
51
4th version: Adding path compression
Proposition [Hopcroft-Ullman, Tarjan]
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
X
X
X
Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects
makes 𝑶(𝒏 + 𝒎 𝐥𝐨𝐠∗
𝒏) work (array, accesses).
log∗
𝑛 is the iterated logarithm log∗ n = ቊ
0 if n ≤ 1
1 + log∗(log2 n) otherwise
log2 1 = 0
log∗ 2 = 1
log∗ 22 = 2
log∗ 222
= 3
log∗ 2222
= 4
log∗ 22222
= 5
Note that 2222
= 216
= 65536. So 22222
= 265536
You are NEVER going to have 𝑛 > 265536
so, for all practical
applications, log∗
𝑛 ≤ 5
52
4th version: Adding path compression
Proposition [Hopcroft-Ullman, Tarjan]
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
𝑥
𝑎1
𝑎1
𝑎𝑘
r
𝑎3
X
X
X
Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects
makes 𝑶(𝒏 + 𝒎 𝐥𝐨𝐠∗
𝒏) work (array, accesses).
Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects
makes 𝑶(𝒏 + 𝒎 𝛂(𝐦, 𝐧)) work (array, accesses) and that’s the best possible!
[Hopcroft-Ullman, Tarjan] actually proved something even better,
𝛂(𝐦, 𝐧) is the inverse Ackermann function, which grows even slower than log∗
𝑛
https://en.wikipedia.org/wiki/Ackermann_function
https://en.wikipedia.org/wiki/Iterated_logarithm

More Related Content

PDF
_b65e7611894ba175de27bd14793f894a_15UnionFind.pdf
PDF
15 unionfind
PDF
Algorithms, Union Find
PPTX
Find operation and smart union algorithm
PPT
DAA (Unit-2) (ii).ppt design analysis of algorithms
PPTX
PPTX
Lecture 6 disjoint set
PPTX
data structure
_b65e7611894ba175de27bd14793f894a_15UnionFind.pdf
15 unionfind
Algorithms, Union Find
Find operation and smart union algorithm
DAA (Unit-2) (ii).ppt design analysis of algorithms
Lecture 6 disjoint set
data structure

Similar to learning about union find algorithm lectures (20)

PPTX
Disjoint set / Union Find Data Structure
DOCX
Algorithm
PPTX
Implementation of union
PDF
Minimum Spanning Trees Artificial Intelligence
PPTX
Set Operations - Union Find and Bloom Filters
PPTX
DISJOINT SETS.pptx
PPTX
Path compression
PPTX
Disjoint sets union, find
PPT
ee220s02lec10.ppt.........................
PPTX
Advanced Algorithms #1 - Union/Find on Disjoint-set Data Structures.
PDF
Gwt presen alsip-20111201
PDF
Declare Your Language: Constraint Resolution 2
PPT
Sets and disjoint sets union123
PPTX
Disjoint set
PPT
DisjointSetsDisjointSets (1)DisjointSets (1)DisjointSets (1)DisjointSets (1) ...
PPT
computer notes - Data Structures - 29
PDF
Time complexity of union find
PDF
smtlecture.7
PPT
computer notes - Data Structures - 30
PPT
Computer notes - Analysis of Union
Disjoint set / Union Find Data Structure
Algorithm
Implementation of union
Minimum Spanning Trees Artificial Intelligence
Set Operations - Union Find and Bloom Filters
DISJOINT SETS.pptx
Path compression
Disjoint sets union, find
ee220s02lec10.ppt.........................
Advanced Algorithms #1 - Union/Find on Disjoint-set Data Structures.
Gwt presen alsip-20111201
Declare Your Language: Constraint Resolution 2
Sets and disjoint sets union123
Disjoint set
DisjointSetsDisjointSets (1)DisjointSets (1)DisjointSets (1)DisjointSets (1) ...
computer notes - Data Structures - 29
Time complexity of union find
smtlecture.7
computer notes - Data Structures - 30
Computer notes - Analysis of Union
Ad

Recently uploaded (20)

PDF
DP Operators-handbook-extract for the Mautical Institute
PPTX
Group 1 Presentation -Planning and Decision Making .pptx
PPTX
Programs and apps: productivity, graphics, security and other tools
PDF
MIND Revenue Release Quarter 2 2025 Press Release
PDF
Hindi spoken digit analysis for native and non-native speakers
PPTX
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
PDF
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
PDF
Univ-Connecticut-ChatGPT-Presentaion.pdf
PDF
Enhancing emotion recognition model for a student engagement use case through...
PDF
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
PPTX
OMC Textile Division Presentation 2021.pptx
PPTX
A Presentation on Touch Screen Technology
PDF
Accuracy of neural networks in brain wave diagnosis of schizophrenia
PDF
Mushroom cultivation and it's methods.pdf
PDF
project resource management chapter-09.pdf
PPTX
SOPHOS-XG Firewall Administrator PPT.pptx
PPTX
Digital-Transformation-Roadmap-for-Companies.pptx
PDF
Agricultural_Statistics_at_a_Glance_2022_0.pdf
PDF
WOOl fibre morphology and structure.pdf for textiles
PPTX
1. Introduction to Computer Programming.pptx
DP Operators-handbook-extract for the Mautical Institute
Group 1 Presentation -Planning and Decision Making .pptx
Programs and apps: productivity, graphics, security and other tools
MIND Revenue Release Quarter 2 2025 Press Release
Hindi spoken digit analysis for native and non-native speakers
TechTalks-8-2019-Service-Management-ITIL-Refresh-ITIL-4-Framework-Supports-Ou...
ENT215_Completing-a-large-scale-migration-and-modernization-with-AWS.pdf
Univ-Connecticut-ChatGPT-Presentaion.pdf
Enhancing emotion recognition model for a student engagement use case through...
Microsoft Solutions Partner Drive Digital Transformation with D365.pdf
OMC Textile Division Presentation 2021.pptx
A Presentation on Touch Screen Technology
Accuracy of neural networks in brain wave diagnosis of schizophrenia
Mushroom cultivation and it's methods.pdf
project resource management chapter-09.pdf
SOPHOS-XG Firewall Administrator PPT.pptx
Digital-Transformation-Roadmap-for-Companies.pptx
Agricultural_Statistics_at_a_Glance_2022_0.pdf
WOOl fibre morphology and structure.pdf for textiles
1. Introduction to Computer Programming.pptx
Ad

learning about union find algorithm lectures

  • 1. CICS 210 Data Structures Union-Find V1 - 11/24/2024 MJ Golin CICS Fall 2024
  • 2. 2 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 3. 3 The Union Find Problem • We’re now returning to graph connectivity. • Will see an algorithm for being able to answer graph connectivity updates quickly. • This will actually be an algorithm for set maintenance (under insertions). 1 9 3 5 4 8 7 6 11 10 2 12 13 Recall graph connectivity (undirected graphs). • Two vertices in a graph are connected if there exists a path from one to the other. • A connected component is a maximal subgraph in which every vertex is connected to every other vertex. Graph to the left has 3 connected components.
  • 4. 4 The Union Find Problem • We’re now returning to graph connectivity • Will see an algorithm for being able to answer graph connectivity updates quickly • This will actually be an algorithm for set maintenance (under insertions) 1 9 3 5 4 8 7 6 11 10 2 12 13 Connected(a,b): query that returns true if and only if a and b are in the same connected component. A B C Find(a): query that returns the name of the component containing a. Find(3) = Find(6) = A; Find(2) = C
  • 5. 5 The Union Find Problem Note that Connected(a,b) is only asking whether a,b are in the same connected component set. A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing We stated this “connected” problem in a graph but remember, graphs model relationships. So this problem can be applied to anything that can be modeled by a relationship graph, e.g., • Pixels in a digital photo. • Computers in a network. • Friends in a social network. • Transistors in a computer chip. • Elements in a mathematical set. • Variable types in a program. We should also point out that connected components in graphs model “equivalence relations”. So we’re really trying to figure out if two item are equivalent to each other in an equivalence relation. 1 9 3 5 4 8 7 6 11 10 2 12 13
  • 6. 6 The Union Find Problem Suppose that we start with no edges. The problem is to add edges and keep track of them in such a way that we can always answer Connected(a,b) efficiently. Union (a,b) will denote adding the edge (a,b). 1 9 3 5 4 8 7 6 Connected(4,7)? Union(4,9) 𝐹𝑎𝑙𝑠𝑒 𝑇𝑟𝑢𝑒 Union(3,5) Connected(4,8)? 𝐹𝑎𝑙𝑠𝑒 Union(3,8) Connected(5,8)? Connected(1,4)? 𝐹𝑎𝑙𝑠𝑒 Union(1,9) Union(9,5) Connected(4,8)? 𝑇𝑟𝑢𝑒 Union(1,3)
  • 7. 7 The Union Find Problem Note that Connected(a,b) is only asking whether a,b are in the same connected component set. A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing 1 9 3 5 4 8 7 6 Connected(4,7)? Union(4,9) 𝐹𝑎𝑙𝑠𝑒 𝑇𝑟𝑢𝑒 Union(3,5) Connected(4,8)? 𝐹𝑎𝑙𝑠𝑒 Union(3,8) Connected(5,8)? Connected(1,4)? 𝐹𝑎𝑙𝑠𝑒 Union(1,9) Union(9,5) Connected(4,8)? 𝑇𝑟𝑢𝑒 Union(1,3) 1 3 {4} 5 6 7 8 {9} 1 3 {4,9} 5 6 7 8 1 3,5 {4,9} 6 7 8 1 3,5,8 {4,9} 6 7 3,5,8 {1,4,9} 6 7 1,3,5,8,4,9 6 7 No Change!
  • 8. 8 The Union Find Problem Note that Connected(a,b) is only asking whether a,b are in the same connected component set. A Union (a,b) will merge the two sets if a,b are in different sets. If they’re in the same set it will do nothing 1 9 3 5 4 8 7 6 We know how to find connected components in time linear in 𝑂(𝑉 + 𝐸) but we don’t want to have to redo the entire algorithm every time we change the graph by adding an edge. We’re now going to develop an algorithm for doing this more efficiently. Our algorithm will be for set maintenance.
  • 9. 9 The Union Find Problem Assume that out items (vertices) are integers on [0, 𝑛 − 1] Want to support • union(p, q) - add an edge between p and q, placing them into the same connected component • find(p) - return the component id (an int) for the vertex p • connected(p, q) - true if and only if p and q are in the same component Every item will have an (integer) id that is the name of the component it belongs. Since connected(p, q) == (find(p) == find(q)) it is unnecessary to derive it further public interface UnionFind { int find(int p); void union(int p, int q); boolean connected(int p, int q); }
  • 10. 10 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 11. 11 First Simple Version 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 𝑖𝑑[𝑖] 0 1 1 0 2 1 • union(p, q) – change all entries whose id equals 𝑖𝑑[𝑝] to 𝑖𝑑[𝑞] • find(p) – return 𝑖𝑑[𝑝] union(2, 0) 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 𝑖𝑑[𝑖] 0 0 0 0 2 0
  • 12. 12 public class QuickFindUF implements UnionFind { private int[] id; public QuickFindUF(int N) { id = new int[N]; for (int i = 0; i < N; i++) { id[i] = i; // each in own component to start } } public int find(int p) { return id[p]; } public void union(int p, int q) { int pid = id[p]; int qid = id[q]; for (int i = 0; i < id.length; i++) { if (id[i] == pid) { id[i] = qid; } } } public boolean connected(int p, int q) { return find(p) == find(q); } } Initialize by having every item in its own component (setting id[i]=i) find(p) just returns p’s ID union(p,q) sets the id of everyone in same set as p to id[q] connected(p,q) returns whether p and q are in the same set
  • 13. 13 First Simple Version 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 𝑖𝑑[𝑖] 0 1 1 0 2 1 • union(p, q) – change all entries whose id equals 𝑖𝑑[𝑝] to 𝑖𝑑[𝑞] • find(p) – return 𝑖𝑑[𝑝] union(2, 0) 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 𝑖𝑑[𝑖] 0 0 0 0 2 0 Bad running time. Can take 𝑂 𝑉 time per step Sequence union(0,1) union(1,2) union(2,3) … union(n-2,n-1) would take Θ 𝑛2 time.
  • 14. 14 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 15. 15 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖; 0 1 2 3 4 5 6 7 8 9 • Items are decomposed into trees. • 𝑖𝑑[𝑖] is parent of 𝑖 in its tree • root 𝑖 is identified by 𝑖𝑑 𝑖 = 𝑖
  • 16. 16 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖; find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝. Example: 𝑓𝑖𝑛𝑑 7 = 𝑓𝑖𝑛𝑑 2 = 𝑓𝑖𝑛𝑑 9 = 9 𝑓𝑖𝑛𝑑 0 = 𝑓𝑖𝑛𝑑 3 = 3 𝑓𝑖𝑛𝑑 5 = 5 0 1 2 3 4 5 6 7 8 9
  • 17. 17 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖; union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑 𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞). 0 1 2 3 4 5 6 7 8 9 Example: 𝑢𝑛𝑖𝑜𝑛(0,1) X X 9 Sets 𝑖𝑑 3 = 𝑓𝑖𝑛𝑑 1 = 9
  • 18. 18 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 19. 19 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 1 2 3 4 5 6 7 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖; • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝. • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑 𝑝 = 𝑓𝑖𝑛𝑑 𝑞 . 0 1 2 3 4 5 6 7 8 9
  • 20. 20 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 1 2 3 4 5 6 7 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(1,2) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 21. 21 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 7 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(1,2) Now Find(1)=Find(2)=2 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 22. 22 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 7 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,2) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 23. 23 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,2) Now Find(1)=Find(2)=Find(7)=2 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 24. 24 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 8 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(8,9) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 25. 25 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(8,9) Now Find(8)=Find(9)=9 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 26. 26 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,8) This will set 𝑖𝑑 𝑓𝑖𝑛𝑑 7 = 𝑖𝑑 𝑓𝑖𝑛𝑑 8 𝑖𝑑 2 = 𝑖𝑑 9 = 9 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 27. 27 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 9 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,8) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 28. 28 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 9 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(0,3) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 29. 29 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(0,3) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 30. 30 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(8,2) Since Find(8)=Find(2)=9 this does nothing • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 31. 31 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 4 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(4,7) Sets id[4]=Find(7)=9 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 32. 32 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(4,7) Sets id[4]=Find(7)=9 • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 33. 33 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(1,4) Since Find(1)=Find(4)=9 this does nothing • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 34. 34 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 3 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(0,5) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 35. 35 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(0,5) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 36. 36 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 9 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,6) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 37. 37 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 6 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(7,6) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 38. 38 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 5 9 5 6 2 9 6 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(2,0) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 39. 39 2nd version: Up trees 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 3 2 9 5 9 5 5 2 9 6 7 6 8 9 Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝 Sets (items in the same component) will be represented by up-trees. Every item will start in its component, with 𝑖𝑑 𝑝 = 𝑝. In the general scenario, the items in a component will be stored the same up-tree. 𝑖𝑑[𝑖] will be the name of another item in the same set “above it” in the up-tree. 0 1 2 3 4 5 6 7 8 9 Union(2,0) • find(p) – return 𝑖𝑑[𝑞] where 𝑞 is the root of the up-tree containing 𝑝 • union(p, q) – if 𝑝 and 𝑞 are in different sets, merge the sets by setting the id of the root of the up-tree containing 𝑝 to be the root of the up-tree containing 𝑞 i.e., 𝑖𝑑[𝑓𝑖𝑛𝑑(𝑝) = 𝑓𝑖𝑛𝑑(𝑞) The highest item in an up-tree is its root. The root 𝑖 of the up-tree has 𝑖𝑑 𝑖 = 𝑖;
  • 40. 40 public class QuickUnion implements UnionFind { private int[] id; public QuickUnion(int N) { id = new int[N]; for (int i = 0; i < N; i++) { id[i] = i; // each in own component to start } } public int find(int p) { while (p != id[p]) { p = id[p]; } return p; } public void union(int p, int q) { id[find(p)] = find(q); } public boolean connected(int p, int q) { return find(p) == find(q); } } Same as before Returns the root of the tree that contains p. Does this by walking up parents in tree until it finds the root, which is the node satisfying 𝑖 = 𝑖𝑑 𝑖 . union(p,q) points root of tree containing p to root of tree containing q. Note: If find[p]=find[q] it points root to itself, not changing anything.
  • 41. 41 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 42. 42 3rd version: Up trees with Union by size Suppose we did union(0,1) union(0,2) union(0,3) … union(0,n-1) What would happen? 0 1 0 1 2 0 1 2 3 0 1 2 3 𝑛 − 2 n − 1 How much time would this require? After the first 𝑖 unions, it takes 𝑖 − 1 steps to implement 𝑓𝑖𝑛𝑑 0 , so total work is σ𝑖=1 𝑛−1 𝑖 − 1 = Θ(𝑛2) The problem is that the trees built are long and narrow. Can you see a way to fix this?
  • 43. 43 3rd version: Union by size The problem was that we made the root of a small tree (one node) the parent of the larger tree. One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree. As an example, consider this scenario we saw earlier 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 9 7 6 8 9 0 1 2 3 4 5 6 7 8 9 As an example, consider this scenario we saw earlier We were asked to do Union(7,8) so we pointed 2 to 9 Since we are doing Union by size, we would point 9 to 2 instead.
  • 44. 44 3rd version: Union by size The problem was that we made the root of a small tree (one node) the parent of the larger tree. One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree. As an example, consider this scenario we saw earlier 1 2 3 5 4 0 𝑖 0 1 2 3 4 5 6 7 8 9 𝑖𝑑[𝑖] 0 2 2 3 4 5 6 2 9 2 7 6 8 9 0 1 2 3 4 5 6 7 8 9 As an example, consider this scenario we saw earlier We were asked to do Union(7,8) so we pointed 2 to 9 Since we are doing Union by size, we would point 9 to 2 instead.
  • 45. 45 3rd version: Union by size (Implementation) The problem was that we made the root of a small tree (one node) the parent of the larger tree. One fix (that works) is to look at the size of the trees and make the root of the LARGER one the root of the combined tree. For each node: Also keep a size variable sz[i]. sz[i] will be the number of nodes in the tree rooted at i (only used if 𝑖 is the root of its up-tree) public void union(int p, int q) { int i = find(p); int j = find(q); if (i == j) return; if (sz[i] < sz[j]) { id[i] = j; sz[j] += sz[i]; } else { id[j] = i; sz[i] += sz[j]; } } i, j are the roots of the two trees If tree rooted at i is larger, make i the root Otherwise, make j the root the roots of the two trees In both cases update the size of the root of the combined tree to reflect thatit now contains everything
  • 46. 46 3rd version: Up trees with Union by size Suppose we now redo our quadratic bad case using union by size union(0,1) union(0,2) union(0,3) … union(0,n-1) Then we would get 0 1 0 1 2 3 0 2 3 𝑛 − 2 n − 1 This only takes 𝑂 1 time per step. We’ll now see that, when using union by size, the trees never get higher than log2 𝑛, so no find or union step requires more than 𝑂(log 𝑛) time. 0 1 2 …
  • 47. 47 3rd version: Up trees with Union by size Theorem: For any 𝑥 let 𝑑 𝑥 be the depth of 𝑥 in its up-tree and 𝑠𝑖𝑧𝑒(𝑥) the # of nodes in its up-tree. Then 2𝑑(𝑥) ≤ 𝑠𝑖𝑧𝑒 𝑥 . Let 𝑛 be the total # of nodes. This means that every union and find operation takes 𝑂(log 𝑛) time Assume theorem is true Since, for every 𝑥, 2𝑑(𝑥) ≤ 𝑠𝑖𝑧𝑒 𝑥 ≤ 𝑛, we get 𝑑 𝑥 ≤ log2 𝑛 , which means that 𝑓𝑖𝑛𝑑(𝑥) never takes more than log2 𝑛 steps. In particular, 𝑛 operations takes 𝑂 𝑛 𝑙𝑜𝑔 𝑛 time, a big improvement from the 𝑂(𝑛2 ) of the previous version.
  • 48. 48 3rd version: Up trees with Union by size • At start, for every node 𝑥, 𝑑(𝑥) = 0 and 𝑠𝑖𝑧𝑒 𝑥 = 1, so 2𝑑(𝑥) = 1 = 𝑠𝑖𝑧𝑒 𝑥 . • Since 𝑑 𝑥 ≤ 𝑑′(𝑥) and 𝑠𝑖𝑧𝑒 𝑥 ≤ 𝑠𝑖𝑧𝑒′ 𝑥 , this can only be violated if 𝑑′ 𝑥 > 𝑑 𝑥 . Without loss of generality assume that 𝑓𝑖𝑛𝑑 𝑥 = 𝑓𝑖𝑛𝑑(𝑝) 𝑑′ 𝑥 > 𝑑 𝑥 can only happen if 𝑓𝑖𝑛𝑑(𝑞) becomes the parent of 𝑓𝑖𝑛𝑑(𝑝). Proof: Consider any union(𝑝, 𝑞) step (only time at which values changes). Let 𝑑 𝑥 , 𝑠𝑖𝑧𝑒(𝑥) be the values before the union and 𝑑′ 𝑥 , 𝑠𝑖𝑧𝑒′(𝑥) the values after the union. For all 𝑥, assume that (∗) is satisfied before the union. We want to show that 2𝑑′ 𝑥 ≤ 𝑠𝑖𝑧𝑒′(𝑥) afterwards as well. ⇒ 2𝑑(𝑥) ≤ 𝑠𝑖𝑧𝑒 𝑥 = 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 ≤ 𝑠𝑖𝑧𝑒(𝑓𝑖𝑛𝑑 𝑞 ) ⇒ 𝑑′(𝑥) = 𝑑 𝑥 + 1; 𝑠𝑖𝑧𝑒′ 𝑥 = 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑(𝑥) + 𝑠𝑖𝑧𝑒(𝑓𝑖𝑛𝑑(𝑞)) ⇒ 2𝑑′(𝑥) = 2 ⋅ 2𝑑 𝑥 ≤ 2 ⋅ 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 ≤ 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑝 + 𝑠𝑖𝑧𝑒 𝑓𝑖𝑛𝑑 𝑞 = 𝑠𝑖𝑧𝑒′(𝑥)! Theorem: For any 𝑥 let 𝑑 𝑥 be the depth of 𝑥 in its up-tree and 𝑠𝑖𝑧𝑒(𝑥) the # of nodes in its up-tree. Then ∗ 2𝑑(𝑥) ≤ 𝑠𝑖𝑧𝑒 𝑥 . 𝑝 𝑞 𝑓𝑖𝑛𝑑(𝑝) 𝑓𝑖𝑛𝑑(𝑞) 𝑠𝑖𝑧𝑒 𝑝 ≤ 𝑠𝑖𝑧𝑒(𝑞) 𝑥
  • 49. 49 Outline • Union Find • Introduction • First version • Up-trees • Union by size • Going further
  • 50. 50 4th version: Adding path compression The running time can be improved via another trick. In find(x), first trace the path from 𝑥 to the root. Let 𝑟 be the root of the tree, and the path from 𝑥 to 𝑟 be 𝑥𝑎1𝑎2 … 𝑎𝑘𝑟. Run through the path again, this time setting all the id’s (parent pointers) of 𝑥, 𝑎1, 𝑎2 , … , 𝑎𝑘 to be the root 𝑟 . 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 X X X This is called Path compression. It requires 𝑓𝑖𝑛𝑑(𝑥) to make two loops. The first to find 𝑟; the second to walk up from 𝑥 again, changing all of the id’s. This will make the trees very shallow!
  • 51. 51 4th version: Adding path compression Proposition [Hopcroft-Ullman, Tarjan] 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 X X X Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects makes 𝑶(𝒏 + 𝒎 𝐥𝐨𝐠∗ 𝒏) work (array, accesses). log∗ 𝑛 is the iterated logarithm log∗ n = ቊ 0 if n ≤ 1 1 + log∗(log2 n) otherwise log2 1 = 0 log∗ 2 = 1 log∗ 22 = 2 log∗ 222 = 3 log∗ 2222 = 4 log∗ 22222 = 5 Note that 2222 = 216 = 65536. So 22222 = 265536 You are NEVER going to have 𝑛 > 265536 so, for all practical applications, log∗ 𝑛 ≤ 5
  • 52. 52 4th version: Adding path compression Proposition [Hopcroft-Ullman, Tarjan] 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 𝑥 𝑎1 𝑎1 𝑎𝑘 r 𝑎3 X X X Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects makes 𝑶(𝒏 + 𝒎 𝐥𝐨𝐠∗ 𝒏) work (array, accesses). Starting from the empty data structure, any sequence of 𝑚 𝑓𝑖𝑛𝑑 operations on 𝑛 objects makes 𝑶(𝒏 + 𝒎 𝛂(𝐦, 𝐧)) work (array, accesses) and that’s the best possible! [Hopcroft-Ullman, Tarjan] actually proved something even better, 𝛂(𝐦, 𝐧) is the inverse Ackermann function, which grows even slower than log∗ 𝑛 https://en.wikipedia.org/wiki/Ackermann_function https://en.wikipedia.org/wiki/Iterated_logarithm