vbl_disjoint_sets.cxx
Go to the documentation of this file.
1 // Disjoint Set Data Structure
2 // Author: Emil Stefanov
3 // Date: 03/28/06
4 // Implementation is as described in http://en.wikipedia.org/wiki/Disjoint-set_data_structure
5 
6 #include <cstddef>
7 #include <cassert>
8 #ifdef _MSC_VER
9 # include <vcl_msvc_warnings.h>
10 #endif
11 
12 #include "vbl_disjoint_sets.h"
13 
14 
16 {
17  num_elements_ = 0;
18  num_sets_ = 0;
19 }
20 
22 {
23  num_elements_ = 0;
24  num_sets_ = 0;
25  add_elements(count);
26 }
27 
29 {
30  this->num_elements_ = s.num_elements_;
31  this->num_sets_ = s.num_sets_;
32 
33  // Copy nodes
34  node nd;
36  for (int i = 0; i < num_elements_; ++i)
37  nodes_[i] = node(s.nodes_[i]);
38 
39  // Update parent pointers to point to newly created nodes rather than the old ones
40  for (int i = 0; i < num_elements_; ++i)
41  if (nodes_[i].parent != nullptr)
42  nodes_[i].parent = &nodes_[s.nodes_[i].parent->index];
43 }
44 
46 {
47  num_elements_ = 0;
48  num_sets_ = 0;
49 }
50 
51 // Note: some internal data is modified for optimization even though this method is consant.
52 int vbl_disjoint_sets::find_set(int element_id) const
53 {
54  assert(element_id < num_elements_);
55 
56  node* curnode;
57 
58  // Find the root element that represents the set which `element_id` belongs to
59  curnode = const_cast<node*>(nodes_.begin() + element_id);
60  while (curnode->parent != nullptr)
61  curnode = curnode->parent;
62  node* root = curnode;
63 
64  // Walk to the root, updating the parents of `element_id`. Make those elements the direct
65  // children of `root`. This optimizes the tree for future find_set invokations.
66  curnode = const_cast<node*>(nodes_.begin()+element_id);
67  while (curnode != root)
68  {
69  node* next = curnode->parent;
70  curnode->parent = root;
71  curnode = next;
72  }
73 
74  return root->index;
75 }
76 
77 void vbl_disjoint_sets::set_union(int setId1, int setId2)
78 {
79  assert(setId1 < num_elements_);
80  assert(setId2 < num_elements_);
81 
82  if (setId1 == setId2)
83  return; // already unioned
84 
85  node* set1 = const_cast<node*>(nodes_.begin()+setId1);
86  node* set2 = const_cast<node*>(nodes_.begin()+setId2);
87 
88  // Determine which node representing a set has a higher rank. The node with the higher rank is
89  // likely to have a bigger subtree so in order to better balance the tree representing the
90  // union, the node with the higher rank is made the parent of the one with the lower rank and
91  // not the other way around.
92  if (set1->rank > set2->rank) {
93  set2->parent = set1;
94  set1->size = set1->size + set2->size;
95  }
96  else if (set1->rank < set2->rank) {
97  set1->parent = set2;
98  set2->size = set2->size + set1->size;
99  }
100  else // set1->rank == set2->rank
101  {
102  set2->parent = set1;
103  ++set1->rank; // update rank
104  set1->size = set1->size + set2->size;
105  }
106 
107  // Since two sets have fused into one, there is now one less set so update the set count.
108  --num_sets_;
109 }
110 
112 {
113  assert(num_to_add >= 0);
114 
115  // insert and initialize the specified number of element nodes to the end of the `nodes_` array
116  int n = nodes_.size();
117  for (int i = n; i < num_to_add + n; ++i)
118  {
119  node nd;
120  nd.index = i;
121  nodes_.push_back(nd);
122  }
123  // update element and set counts
124  num_elements_ += num_to_add;
125  num_sets_ += num_to_add;
126 }
127 
129 {
130  return num_elements_;
131 }
132 
134 {
135  return num_sets_;
136 }
137 
138 int vbl_disjoint_sets::size(int set_id) const
139 {
140  assert(set_id < num_elements_);
141  return nodes_[set_id].size;
142 }
int rank
represents the approximate max height of the node in its subtree.
void add_elements(int num_to_add)
~vbl_disjoint_sets()
Destructor.
vbl_array_1d< node > nodes_
A simple container.
Definition: vbl_array_1d.h:28
implements a disjoint set (union, find)
void set_union(int set_id1, int set_id2)
Combine two sets into one.
int find_set(int element) const
Find the set identifier that an element currently belongs to.
int num_sets() const
Returns the number of sets.
int size(int set_id) const
Returns the number of elements in set specified by set_id.