Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 1 | |
Marijn Haverbeke | 3816e57 | 2011-05-12 15:24:54 | [diff] [blame] | 2 | import option::none; |
| 3 | import option::some; |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 4 | |
Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 5 | |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 6 | // A very naive implementation of union-find with unsigned integer nodes. |
Patrick Walton | 4eb476f | 2011-05-20 22:46:01 | [diff] [blame] | 7 | // Maintains the invariant that the root of a node is always equal to or less |
| 8 | // than the node itself. |
Marijn Haverbeke | 3816e57 | 2011-05-12 15:24:54 | [diff] [blame] | 9 | type node = option::t[uint]; |
Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 10 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 11 | type ufind = {mutable nodes: vec[mutable node]}; |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 12 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 13 | fn make() -> ufind { ret {mutable nodes: [mutable ]}; } |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 14 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 15 | fn make_set(ufnd: &ufind) -> uint { |
| 16 | let idx = vec::len(ufnd.nodes); |
Graydon Hoare | fbbc1a7 | 2011-05-17 01:21:22 | [diff] [blame] | 17 | ufnd.nodes += [mutable none[uint]]; |
Patrick Walton | ec5a60d | 2011-04-08 21:53:16 | [diff] [blame] | 18 | ret idx; |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 19 | } |
| 20 | |
Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 21 | |
Patrick Walton | ddec6b5 | 2011-05-21 01:36:35 | [diff] [blame] | 22 | /// Creates sets as necessary to ensure that least `n` sets are present in the |
| 23 | /// data structure. |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 24 | fn grow(ufnd: &ufind, n: uint) { |
| 25 | while set_count(ufnd) < n { make_set(ufnd); } |
Patrick Walton | ddec6b5 | 2011-05-21 01:36:35 | [diff] [blame] | 26 | } |
| 27 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 28 | fn find(ufnd: &ufind, n: uint) -> uint { |
| 29 | alt ufnd.nodes.(n) { |
| 30 | none. { ret n; } |
| 31 | some(m) { let m_ = m; be find(ufnd, m_); } |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 32 | } |
| 33 | } |
| 34 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 35 | fn union(ufnd: &ufind, m: uint, n: uint) { |
| 36 | let m_root = find(ufnd, m); |
| 37 | let n_root = find(ufnd, n); |
| 38 | if m_root < n_root { |
Patrick Walton | 4eb476f | 2011-05-20 22:46:01 | [diff] [blame] | 39 | ufnd.nodes.(n_root) = some[uint](m_root); |
Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 40 | } else if (m_root > n_root) { ufnd.nodes.(m_root) = some[uint](n_root); } |
Patrick Walton | 4eb476f | 2011-05-20 22:46:01 | [diff] [blame] | 41 | } |
| 42 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 43 | fn set_count(ufnd: &ufind) -> uint { ret vec::len[node](ufnd.nodes); } |
Graydon Hoare | ce72993 | 2011-06-15 18:19:50 | [diff] [blame] | 44 | |
Patrick Walton | ddec6b5 | 2011-05-21 01:36:35 | [diff] [blame] | 45 | |
Patrick Walton | 4eb476f | 2011-05-20 22:46:01 | [diff] [blame] | 46 | // Removes all sets with IDs greater than or equal to the given value. |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 47 | fn prune(ufnd: &ufind, n: uint) { |
Patrick Walton | 4eb476f | 2011-05-20 22:46:01 | [diff] [blame] | 48 | // TODO: Use "slice" once we get rid of "mutable?" |
Patrick Walton | afa6d85 | 2011-04-08 01:01:21 | [diff] [blame] | 49 | |
Marijn Haverbeke | df7f21d | 2011-07-27 12:19:39 | [diff] [blame^] | 50 | let len = vec::len[node](ufnd.nodes); |
| 51 | while len != n { vec::pop[node](ufnd.nodes); len -= 1u; } |
| 52 | } |