37 #ifndef VIGRA_UNION_FIND_HXX
38 #define VIGRA_UNION_FIND_HXX
46 #include "array_vector.hxx"
47 #include "iteratoradapter.hxx"
53 template <
class T,
class IsSigned = VigraFalseType>
54 struct UnionFindAccessorImpl
56 static const T max_label = NumericTraits<T>::maxConst >> 1;
57 static const T anchor_bit = ~max_label;
64 static T deletedAnchor()
66 return NumericTraits<T>::maxConst;
69 static bool isAnchor(T
const & t)
71 return (t & anchor_bit) != 0;
74 static bool isValidAnchor(T
const & t)
76 return isAnchor(t) && t != deletedAnchor();
79 static bool notAnchor(T
const & t)
81 return (t & anchor_bit) == 0;
84 static T toAnchor(T
const & t)
86 return t | anchor_bit;
89 static T fromAnchor(T
const & t)
96 struct UnionFindAccessorImpl<T, VigraTrueType>
100 return NumericTraits<T>::max();
103 static T deletedAnchor()
105 return NumericTraits<T>::min();
108 static bool isAnchor(T
const & t)
113 static bool isValidAnchor(T
const & t)
115 return isAnchor(t) && t != deletedAnchor();
118 static bool notAnchor(T
const & t)
123 static T toAnchor(T
const & t)
128 static T fromAnchor(T
const & t)
134 template <
class Array,
class LabelAccessor>
135 class UnionFindIteratorPolicy
138 typedef UnionFindIteratorPolicy BaseType;
139 typedef typename Array::difference_type value_type;
140 typedef typename Array::difference_type difference_type;
141 typedef value_type
const & reference;
142 typedef value_type
const & index_reference;
143 typedef value_type
const * pointer;
144 typedef typename std::forward_iterator_tag iterator_category;
146 Array
const & array_;
149 UnionFindIteratorPolicy(Array
const & array, value_type index=0)
154 static void initialize(BaseType & d)
159 static reference dereference(BaseType
const & d)
164 static bool equal(BaseType
const & d1, BaseType
const & d2)
166 return d1.index_ == d2.index_;
169 static bool less(BaseType
const & d1, BaseType
const & d2)
171 return d1.index_ < d2.index_;
174 static void increment(BaseType & d)
180 static void advanceToAnchor(BaseType & d)
182 while(d.index_ < (value_type)d.array_.size()-1 &&
183 !LabelAccessor::isValidAnchor(d.array_[d.index_]))
195 typedef ArrayVector<T> LabelArray;
196 typedef typename LabelArray::difference_type IndexType;
197 typedef detail::UnionFindAccessorImpl<T,
198 typename NumericTraits<T>::isSigned> LabelAccessor;
199 typedef detail::UnionFindIteratorPolicy<LabelArray, LabelAccessor> IteratorPolicy;
200 typedef IteratorAdaptor<IteratorPolicy> iterator;
201 typedef iterator const_iterator;
203 mutable ArrayVector<T> labels_;
206 UnionFindArray(T next_free_label = 1)
208 vigra_precondition(next_free_label <= LabelAccessor::max(),
209 "UnionFindArray(): Need more labels than can be represented"
210 "in the destination type.");
212 for(T k=0; k < next_free_label; ++k)
213 labels_.push_back(LabelAccessor::toAnchor(k));
214 labels_.push_back(LabelAccessor::toAnchor(next_free_label));
217 const_iterator begin(
unsigned int start_at=0)
const
219 return const_iterator(IteratorPolicy(labels_, start_at));
222 const_iterator end()
const
224 return const_iterator(IteratorPolicy(labels_, labels_.size()-1));
227 T nextFreeIndex()
const
229 return T(labels_.size() - 1);
232 T findIndex(T index)
const
234 IndexType root = index;
235 while(LabelAccessor::notAnchor(labels_[root]))
236 root = (IndexType)labels_[root];
238 while((IndexType)index != root)
240 T next = labels_[(IndexType)index];
241 labels_[(IndexType)index] = root;
247 T findLabel(T index)
const
249 return LabelAccessor::fromAnchor(labels_[findIndex(index)]);
252 void deleteIndex(T index)
254 labels_[findIndex(index)] = LabelAccessor::deletedAnchor();
258 T makeUnion(T l1, T l2)
260 IndexType i1 = findIndex(l1);
261 IndexType i2 = findIndex(l2);
278 T finalizeIndex(T index)
280 if(index == (T)labels_.size()-1)
283 vigra_invariant(index < LabelAccessor::max(),
284 "connected components: Need more labels than can be represented in the destination type.");
286 labels_.push_back(LabelAccessor::toAnchor((T)labels_.size()));
291 labels_.back() = LabelAccessor::toAnchor((T)labels_.size()-1);
298 T index = LabelAccessor::fromAnchor(labels_.back());
299 vigra_invariant(index < LabelAccessor::max(),
300 "connected components: Need more labels than can be represented in the destination type.");
301 labels_.push_back(LabelAccessor::toAnchor((T)labels_.size()));
305 unsigned int makeContiguous()
308 unsigned int count = 0;
309 for(IndexType i=0; i<(IndexType)(labels_.size()-1); ++i)
311 if(LabelAccessor::isValidAnchor(labels_[i]))
313 labels_[i] = LabelAccessor::toAnchor((T)count++);
317 labels_[i] = findIndex(i);
326 #endif // VIGRA_UNION_FIND_HXX