COIN-OR::LEMON - Graph Library

source: lemon-0.x/lemon/unionfind.h @ 2390:8450951a8e2d

Last change on this file since 2390:8450951a8e2d was 2386:81b47fc5c444, checked in by Balazs Dezso, 17 years ago

Hard Warning checking

  • based on the remark of the ZIB user
  • we do not use -Winline
File size: 15.8 KB
RevLine 
[906]1/* -*- C++ -*-
2 *
[1956]3 * This file is a part of LEMON, a generic C++ optimization library
4 *
5 * Copyright (C) 2003-2006
6 * Egervary Jeno Kombinatorikus Optimalizalasi Kutatocsoport
[1359]7 * (Egervary Research Group on Combinatorial Optimization, EGRES).
[906]8 *
9 * Permission to use, modify and distribute this software is granted
10 * provided that this copyright notice appears in all copies. For
11 * precise terms see the accompanying LICENSE file.
12 *
13 * This software is provided "AS IS" with no warranty of any kind,
14 * express or implied, and with no claim as to its suitability for any
15 * purpose.
16 *
17 */
18
[921]19#ifndef LEMON_UNION_FIND_H
20#define LEMON_UNION_FIND_H
[483]21
[491]22//!\ingroup auxdat
[483]23//!\file
24//!\brief Union-Find data structures.
[774]25//!
[483]26
27#include <vector>
28#include <list>
29#include <utility>
30#include <algorithm>
31
[1993]32#include <lemon/bits/invalid.h>
[483]33
[921]34namespace lemon {
[483]35
[2308]36  /// \ingroup auxdat
37  ///
[2205]38  /// \brief A \e Union-Find data structure implementation
39  ///
40  /// The class implements the \e Union-Find data structure.
41  /// The union operation uses rank heuristic, while
42  /// the find operation uses path compression.
43  /// This is a very simple but efficient implementation, providing
44  /// only four methods: join (union), find, insert and size.
45  /// For more features see the \ref UnionFindEnum class.
46  ///
47  /// It is primarily used in Kruskal algorithm for finding minimal
48  /// cost spanning tree in a graph.
49  /// \sa kruskal()
50  ///
51  /// \pre You need to add all the elements by the \ref insert()
52  /// method. 
[2308]53  template <typename _ItemIntMap>
[483]54  class UnionFind {
55  public:
[2308]56
57    typedef _ItemIntMap ItemIntMap;
58    typedef typename ItemIntMap::Key Item;
[483]59
60  private:
[2205]61    // If the items vector stores negative value for an item then
62    // that item is root item and it has -items[it] component size.
63    // Else the items[it] contains the index of the parent.
64    std::vector<int> items;
65    ItemIntMap& index;
66
67    bool rep(int idx) const {
68      return items[idx] < 0;
69    }
70
71    int repIndex(int idx) const {
72      int k = idx;
73      while (!rep(k)) {
74        k = items[k] ;
75      }
76      while (idx != k) {
77        int next = items[idx];
78        const_cast<int&>(items[idx]) = k;
79        idx = next;
80      }
81      return k;
82    }
[483]83
84  public:
85
[2205]86    /// \brief Constructor
87    ///
88    /// Constructor of the UnionFind class. You should give an item to
89    /// integer map which will be used from the data structure. If you
90    /// modify directly this map that may cause segmentation fault,
91    /// invalid data structure, or infinite loop when you use again
92    /// the union-find.
93    UnionFind(ItemIntMap& m) : index(m) {}
[483]94
[2205]95    /// \brief Returns the index of the element's component.
96    ///
97    /// The method returns the index of the element's component.
98    /// This is an integer between zero and the number of inserted elements.
99    ///
100    int find(const Item& a) {
101      return repIndex(index[a]);
[483]102    }
103
[2205]104    /// \brief Inserts a new element into the structure.
105    ///
106    /// This method inserts a new element into the data structure.
107    ///
108    /// The method returns the index of the new component.
109    int insert(const Item& a) {
110      int n = items.size();
111      items.push_back(-1);
112      index.set(a,n);
[483]113      return n;
114    }
115
[2205]116    /// \brief Joining the components of element \e a and element \e b.
117    ///
118    /// This is the \e union operation of the Union-Find structure.
119    /// Joins the component of element \e a and component of
120    /// element \e b. If \e a and \e b are in the same component then
121    /// it returns false otherwise it returns true.
122    bool join(const Item& a, const Item& b) {
123      int ka = repIndex(index[a]);
124      int kb = repIndex(index[b]);
[483]125
[2205]126      if ( ka == kb )
[483]127        return false;
128
[2205]129      if (items[ka] < items[kb]) {
130        items[ka] += items[kb];
131        items[kb] = ka;
132      } else {
133        items[kb] += items[ka];
134        items[ka] = kb;
[483]135      }
136      return true;
137    }
138
[2205]139    /// \brief Returns the size of the component of element \e a.
140    ///
141    /// Returns the size of the component of element \e a.
142    int size(const Item& a) {
143      int k = repIndex(index[a]);
144      return - items[k];
[483]145    }
146
147  };
148
[2308]149  /// \ingroup auxdat
150  ///
[2205]151  /// \brief A \e Union-Find data structure implementation which
152  /// is able to enumerate the components.
153  ///
154  /// The class implements a \e Union-Find data structure
155  /// which is able to enumerate the components and the items in
156  /// a component. If you don't need this feature then perhaps it's
157  /// better to use the \ref UnionFind class which is more efficient.
158  ///
159  /// The union operation uses rank heuristic, while
160  /// the find operation uses path compression.
161  ///
162  /// \pre You need to add all the elements by the \ref insert()
163  /// method.
164  ///
[2308]165  template <typename _ItemIntMap>
[2205]166  class UnionFindEnum {
167  public:
168   
169    typedef _ItemIntMap ItemIntMap;
[2308]170    typedef typename ItemIntMap::Key Item;
171
[2205]172  private:
173   
174    // If the parent stores negative value for an item then that item
175    // is root item and it has -items[it].parent component size.  Else
176    // the items[it].parent contains the index of the parent.
177    //
178    // The \c nextItem and \c prevItem provides the double-linked
179    // cyclic list of one component's items. The \c prevClass and
180    // \c nextClass gives the double linked list of the representant
181    // items.
182    struct ItemT {
183      int parent;
184      Item item;
[483]185
[2205]186      int nextItem, prevItem;
187      int nextClass, prevClass;
188    };
[483]189
[2205]190    std::vector<ItemT> items;
191    ItemIntMap& index;
[483]192
[2205]193    int firstClass;
[483]194
195
[2205]196    bool rep(int idx) const {
197      return items[idx].parent < 0;
[483]198    }
199
[2205]200    int repIndex(int idx) const {
201      int k = idx;
202      while (!rep(k)) {
203        k = items[k].parent;
204      }
205      while (idx != k) {
206        int next = items[idx].parent;
207        const_cast<int&>(items[idx].parent) = k;
208        idx = next;
209      }
210      return k;
211    }
212
213    void unlaceClass(int k) {
214      if (items[k].prevClass != -1) {
215        items[items[k].prevClass].nextClass = items[k].nextClass;
216      } else {
217        firstClass = items[k].nextClass;
218      }
219      if (items[k].nextClass != -1) {
220        items[items[k].nextClass].prevClass = items[k].prevClass;
221      }
222    }
223
224    void spliceItems(int ak, int bk) {
225      items[items[ak].prevItem].nextItem = bk;
226      items[items[bk].prevItem].nextItem = ak;
227      int tmp = items[ak].prevItem;
228      items[ak].prevItem = items[bk].prevItem;
229      items[bk].prevItem = tmp;
230       
[2003]231    }
232
[483]233  public:
234
[2205]235    UnionFindEnum(ItemIntMap& _index)
236      : items(), index(_index), firstClass(-1) {}
237   
238    /// \brief Inserts the given element into a new component.
239    ///
240    /// This method creates a new component consisting only of the
241    /// given element.
242    ///
243    void insert(const Item& item) {
244      ItemT t;
[483]245
[2205]246      int idx = items.size();
247      index.set(item, idx);
[483]248
[2205]249      t.nextItem = idx;
250      t.prevItem = idx;
251      t.item = item;
252      t.parent = -1;
253     
254      t.nextClass = firstClass;
255      if (firstClass != -1) {
256        items[firstClass].prevClass = idx;
257      }
258      t.prevClass = -1;
259      firstClass = idx;
[483]260
[2205]261      items.push_back(t);
[483]262    }
263
[2205]264    /// \brief Inserts the given element into the component of the others.
265    ///
266    /// This methods inserts the element \e a into the component of the
267    /// element \e comp.
268    void insert(const Item& item, const Item& comp) {
269      int k = repIndex(index[comp]);
270      ItemT t;
[483]271
[2205]272      int idx = items.size();
273      index.set(item, idx);
274
275      t.prevItem = k;
276      t.nextItem = items[k].nextItem;
277      items[items[k].nextItem].prevItem = idx;
278      items[k].nextItem = idx;
279
280      t.item = item;
281      t.parent = k;
282
283      --items[k].parent;
284
285      items.push_back(t);
[483]286    }
287
[2205]288    /// \brief Finds the leader of the component of the given element.
289    ///
290    /// The method returns the leader of the component of the given element.
291    const Item& find(const Item &item) const {
292      return items[repIndex(index[item])].item;
[483]293    }
294
[2205]295    /// \brief Joining the component of element \e a and element \e b.
296    ///
297    /// This is the \e union operation of the Union-Find structure.
298    /// Joins the component of element \e a and component of
299    /// element \e b. If \e a and \e b are in the same component then
300    /// returns false else returns true.
301    bool join(const Item& a, const Item& b) {
[483]302
[2205]303      int ak = repIndex(index[a]);
304      int bk = repIndex(index[b]);
[483]305
[2205]306      if (ak == bk) {
[483]307        return false;
308      }
309
[2205]310      if ( items[ak].parent < items[bk].parent ) {
311        unlaceClass(bk);
312        items[ak].parent += items[bk].parent;
313        items[bk].parent = ak;
314      } else {
[2332]315        unlaceClass(ak);
[2205]316        items[bk].parent += items[ak].parent;
317        items[ak].parent = bk;
[483]318      }
[2205]319      spliceItems(ak, bk);
[483]320
321      return true;
322    }
323
[2205]324    /// \brief Returns the size of the component of element \e a.
325    ///
326    /// Returns the size of the component of element \e a.
327    int size(const Item &item) const {
328      return - items[repIndex(index[item])].parent;
[483]329    }
330
[2205]331    /// \brief Splits up the component of the element.
332    ///
333    /// Splitting the component of the element into sigleton
334    /// components (component of size one).
335    void split(const Item &item) {
336      int k = repIndex(index[item]);
337      int idx = items[k].nextItem;
338      while (idx != k) {
339        int next = items[idx].nextItem;
340       
341        items[idx].parent = -1;
342        items[idx].prevItem = idx;
343        items[idx].nextItem = idx;
344       
345        items[idx].nextClass = firstClass;
346        items[firstClass].prevClass = idx;
347        firstClass = idx;
[483]348
[2205]349        idx = next;
[483]350      }
351
[2205]352      items[idx].parent = -1;
353      items[idx].prevItem = idx;
354      items[idx].nextItem = idx;
355     
356      items[firstClass].prevClass = -1;
[483]357    }
358
[2205]359    /// \brief Sets the given element to the leader element of its component.
360    ///
361    /// Sets the given element to the leader element of its component.
362    void makeRep(const Item &item) {
363      int nk = index[item];
364      int k = repIndex(nk);
365      if (nk == k) return;
366     
367      if (items[k].prevClass != -1) {
368        items[items[k].prevClass].nextClass = nk;
369      } else {
370        firstClass = nk;
371      }
372      if (items[k].nextClass != -1) {
373        items[items[k].nextClass].prevClass = nk;
374      }
375     
376      int idx = items[k].nextItem;
377      while (idx != k) {
378        items[idx].parent = nk;
379        idx = items[idx].nextItem;
380      }
381     
382      items[nk].parent = items[k].parent;
383      items[k].parent = nk;
[483]384    }
385
[2205]386    /// \brief Removes the given element from the structure.
387    ///
388    /// Removes the element from its component and if the component becomes
389    /// empty then removes that component from the component list.
390    ///
391    /// \warning It is an error to remove an element which is not in
392    /// the structure.
393    void erase(const Item &item) {
394      int idx = index[item];
395      if (rep(idx)) {
396        int k = idx;
397        if (items[k].parent == -1) {
398          unlaceClass(idx);
399          return;
400        } else {
401          int nk = items[k].nextItem;
402          if (items[k].prevClass != -1) {
403            items[items[k].prevClass].nextClass = nk;
404          } else {
405            firstClass = nk;
406          }
407          if (items[k].nextClass != -1) {
408            items[items[k].nextClass].prevClass = nk;
409          }
410     
[2386]411          int l = items[k].nextItem;
412          while (l != k) {
413            items[l].parent = nk;
414            l = items[l].nextItem;
[2205]415          }
416         
417          items[nk].parent = items[k].parent + 1;
418        }
419      } else {
420       
421        int k = repIndex(idx);
422        idx = items[k].nextItem;
423        while (idx != k) {
424          items[idx].parent = k;
425          idx = items[idx].nextItem;
426        }
[483]427
[2205]428        ++items[k].parent;
[483]429      }
430
[2205]431      idx = index[item];     
432      items[items[idx].prevItem].nextItem = items[idx].nextItem;
433      items[items[idx].nextItem].prevItem = items[idx].prevItem;
[483]434
[2205]435    }   
[483]436
[2205]437    /// \brief Moves the given element to another component.
438    ///
439    /// This method moves the element \e a from its component
440    /// to the component of \e comp.
441    /// If \e a and \e comp are in the same component then
442    /// it returns false otherwise it returns true.
443    bool move(const Item &item, const Item &comp) {
444      if (repIndex(index[item]) == repIndex(index[comp])) return false;
445      erase(item);
446      insert(item, comp);
[483]447      return true;
448    }
449
450
[2205]451    /// \brief Removes the component of the given element from the structure.
452    ///
453    /// Removes the component of the given element from the structure.
454    ///
455    /// \warning It is an error to give an element which is not in the
456    /// structure.
457    void eraseClass(const Item &item) {
458      unlaceClass(repIndex(index[item]));
459    }
[483]460
[2205]461    /// \brief Lemon style iterator for the representant items.
462    ///
463    /// ClassIt is a lemon style iterator for the components. It iterates
464    /// on the representant items of the classes.
465    class ClassIt {
466    public:
467      /// \brief Constructor of the iterator
468      ///
469      /// Constructor of the iterator
470      ClassIt(const UnionFindEnum& ufe) : unionFind(&ufe) {
471        idx = unionFind->firstClass;
[483]472      }
473
[2205]474      /// \brief Constructor to get invalid iterator
475      ///
476      /// Constructor to get invalid iterator
477      ClassIt(Invalid) : unionFind(0), idx(-1) {}
478     
479      /// \brief Increment operator
480      ///
481      /// It steps to the next representant item.
482      ClassIt& operator++() {
483        idx = unionFind->items[idx].nextClass;
484        return *this;
485      }
486     
487      /// \brief Conversion operator
488      ///
489      /// It converts the iterator to the current representant item.
490      operator const Item&() const {
491        return unionFind->items[idx].item;
[483]492      }
493
[2205]494      /// \brief Equality operator
495      ///
496      /// Equality operator
497      bool operator==(const ClassIt& i) {
498        return i.idx == idx;
499      }
[483]500
[2205]501      /// \brief Inequality operator
502      ///
503      /// Inequality operator
504      bool operator!=(const ClassIt& i) {
505        return i.idx != idx;
[2003]506      }
[483]507     
[2205]508    private:
509      const UnionFindEnum* unionFind;
510      int idx;
511    };
512
513    /// \brief Lemon style iterator for the items of a component.
514    ///
515    /// ClassIt is a lemon style iterator for the components. It iterates
516    /// on the items of a class. By example if you want to iterate on
517    /// each items of each classes then you may write the next code.
518    ///\code
519    /// for (ClassIt cit(ufe); cit != INVALID; ++cit) {
520    ///   std::cout << "Class: ";
521    ///   for (ItemIt iit(ufe, cit); iit != INVALID; ++iit) {
522    ///     std::cout << toString(iit) << ' ' << std::endl;
523    ///   }
524    ///   std::cout << std::endl;
525    /// }
526    ///\endcode
527    class ItemIt {
528    public:
529      /// \brief Constructor of the iterator
530      ///
531      /// Constructor of the iterator. The iterator iterates
532      /// on the class of the \c item.
533      ItemIt(const UnionFindEnum& ufe, const Item& item) : unionFind(&ufe) {
534        idx = unionFind->repIndex(unionFind->index[item]);
[483]535      }
536
[2205]537      /// \brief Constructor to get invalid iterator
538      ///
539      /// Constructor to get invalid iterator
540      ItemIt(Invalid) : unionFind(0), idx(-1) {}
541     
542      /// \brief Increment operator
543      ///
544      /// It steps to the next item in the class.
545      ItemIt& operator++() {
546        idx = unionFind->items[idx].nextItem;
547        if (unionFind->rep(idx)) idx = -1;
548        return *this;
[2003]549      }
[2205]550     
551      /// \brief Conversion operator
552      ///
553      /// It converts the iterator to the current item.
554      operator const Item&() const {
555        return unionFind->items[idx].item;
[2003]556      }
557
[2205]558      /// \brief Equality operator
559      ///
560      /// Equality operator
561      bool operator==(const ItemIt& i) {
562        return i.idx == idx;
[2003]563      }
564
[2205]565      /// \brief Inequality operator
566      ///
567      /// Inequality operator
568      bool operator!=(const ItemIt& i) {
569        return i.idx != idx;
570      }
571     
572    private:
573      const UnionFindEnum* unionFind;
574      int idx;
[483]575    };
576
577  };
578
579
580  //! @}
581
[921]582} //namespace lemon
[483]583
[921]584#endif //LEMON_UNION_FIND_H
Note: See TracBrowser for help on using the repository browser.