Lecture 15
Lecture 15
POW
CS E 3 2 6 : D a ta S tr u c tur e s
Lecture #15
(E q u iv a le n c e ) D u o:
The Dynamic
We ig h te d U n io n & P a th
Compression
Bart Niswonge
W r Zap
!
ha S u mm e r Q u a r t
ck
!!
e r 20 01
Today’s Outline
• Project
– Rules of competition
• Making a “good” maze
• Disjoint Set Union/Find ADT
• Up-trees
• Weighted Unions
• Path Compression
Unix Tutorial!!
Useful tools
• Tuesday, July 31 st
grep, egrep/grep -e
sort
– 10:50am, Sieg 322 cut
file
tr
Printing worksheet find, xargs
Shell diff, patch
which, locate, whereis
different shell quotes : ' `
scripting, #!
Finding info
Techniques
alias
Resources (ACM webpage, web,
variables / environment internal docs)
redirection, piping Process management
File management/permissions
Filesystem layout
What’s a Good Maze?
The Maze Construction Problem
• Given:
– collection of rooms: V
– connections between rooms (initially all
closed): E
• Construct a maze:
– collection of rooms: V = V
– designated rooms in, iV, and out, oV
– collection of connections to knock down:
E E such that one unique path
connects every two rooms
The Middle of the Maze
• So far, a number of walls
have been knocked
down while others
remain. A
• Now, we consider the
wall between A and B.
• Should we knock it B
down?
– if A and B are otherwise
connected
– if A and B are not
otherwise connected
Maze Construction Algorithm
While edges remain in E
Remove a random edge e = (u, v)
from E
If u and v have not yet been
connected
- add e to E
- mark u and v as connected
Mysterious note:
We’ll see this algorithm again!
Equivalence Relations
An equivalence relation R must have three properties
– reflexive: for any x, xRx is true
– symmetric: for any x and y, xRy implies yRx
– transitive: for any x, y, and z, xRy and yRz implies xRz
†
AKA the dynamic equivalence problem
Example
Construct the maze on a 3 b 10 c
the right
2 1 6
find(b) b 2 1 6
find(e) e
find(b) find(e) so: d 4 e 7 f
add 1 to E 11 9 8
union(b, e)
g 12 h 5 i
{a}{b,e}{c}{d}{f}{g}{h}{i}
Order of edges in blue
Example, Continued
{a}{b,e}{c}{d}{f}{g}{h}{i} a 3 b 10 c
2 6
d 4 e 7 f
11 9 8
g 12 h 5 i
a c g h
d e 7 f
11 9 8
d b f i
g 12 h i
a c g h
d e f
11 9 8
d b f i
g 12 h i
union(b,e) g 12 h 5 i
a b c d e f g h i
a b c d f g h i
e
a 3 b 10 c
2 6
union(a,d) g 12 h 5 i
a b c d f g h i
e
a b c f g h i
d e
a 3 b 10 c
6
union(a,b) g 12 h 5 i
a b c f g h i
d e
a c f g h i
b d
e
a b 10 c
6
find(d) = find(e) g 12 h 5 i
No union!
a c f g h i
b d
e
union(h,i) g 12 h 5 i
a c f g h i a c f g h
b d b d i
e e
a b 10 c
6
union(c,f) g 12 h i
a c f g h a c g h
b d i b d f i
e e
a b 10 c
c g h
a c g h
b d f a f i
i
e b d
Could we do a
better job on this union? e
a b 10 c
c g
c g h
a f a f h
i
b d b d i
e e
a b 10 c
c g
a f h
b d i
e
a b c
g
c g
c
a f h
a f h
b d i b d i
e e
a b c
find(g) = find(h)
So, no union. g 12 h i
And, we’re done!
g a b c
c d e f
a f h
g h i
b d i
Ooh… scary!
e Such a hard maze!
Nifty storage trick
A forest of up-trees
can easily be
a c g h
stored in an array.
Also, if the node
names are b d f i
integers or
characters, we
e
can use a very
simple, perfect
hash. 0 (a) 1 (b) 2 (c) 3 (d) 4 (e) 5 (f) 6 (g) 7 (h) 8 (i)
up-index: -1 0 -1 0 1 2 -1 -1 7
Implementation
typedef ID int;
ID find(Object x) { ID union(ID x, ID y) {
assert(hTable.contains(x)); assert(up[x] == -1);
ID parentID = hTable[x]; assert(up[y] == -1);
return parentID;
}
runtime: O(depth) or … runtime: O(1)
Improvement: Weighted Union
• Always makes the root of the larger tree the new
root
• Often cuts down on height of the new up-tree
a c g h c g h a g h
b d f i a f i b d c i
e b d e f
Could we do a e
better job on this union? Weighted union!
Weighted Union Code
typedef ID int;
ID union(ID x, ID y) {
assert(up[x] == -1);
assert(up[y] == -1);
a c f g h i a c f g h i
b d b d
e e
While we’re finding e, Path compression!
could we do anything else?
Path Compression Example
find(e)
c g c g
a f h a f h
b e
b d
d
i
i e
Path Compression Code
typedef ID int;
ID find(Object x) {
assert(hTable.contains(x));
ID parentID = hTable[x];
ID hold = parentID;
while(up[parentID] != -1) {
parentID = up[parentID];
}
ID rootID = parentID;
while(up[hold] != -1) {
ID oldParentID = up[hold];
up[hold] = rootID;
hold = oldParentID;
}
}
return rootID;
runtime:
Digression:
Doping at the Silicon Downs
How fast does log n grow? log n = 4 for n = 16
Let log(k) n = log (log (log … (log n)))
k logs
Then, let log* n = minimum k such that log(k) n 1
How fast does log* n grow? log* n = 4 for n = 65536