unionFind.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. /****************************************************************************
  2. *
  3. * MODULE: r.terraflow
  4. *
  5. * COPYRIGHT (C) 2007 Laura Toma
  6. *
  7. * This program is free software; you can redistribute it and/or modify
  8. * it under the terms of the GNU General Public License as published by
  9. * the Free Software Foundation; either version 2 of the License, or
  10. * (at your option) any later version.
  11. *
  12. * This program is distributed in the hope that it will be useful,
  13. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  15. * GNU General Public License for more details.
  16. *
  17. *****************************************************************************/
  18. #ifndef __UNION_FIND
  19. #define __UNION_FIND
  20. #include <assert.h>
  21. #include <stdlib.h>
  22. #include <string.h>
  23. #include <iostream>
  24. using namespace std;
  25. /* initial range guesstimate */
  26. #define UNION_INITIAL_SIZE 2000
  27. /* maintains a collection of disjoint dynamic sets; elements are in
  28. the range 1..maxsize-1 and range is increased dynamically; if element x
  29. is not in the set then parent[x] = 0;
  30. */
  31. template<class T>
  32. class unionFind {
  33. private:
  34. T* parent;
  35. T* rank;
  36. T maxsize;
  37. public:
  38. unionFind();
  39. ~unionFind();
  40. /* return true if element x is in the structure */
  41. inline bool inSet(T x);
  42. void print();
  43. /* create a new set whose only member (and representative) is x;
  44. since x is disjoint we require x not be already in the set; */
  45. inline void makeSet(T x);
  46. /* unites the dynamic sets that contain x and y; */
  47. inline void makeUnion(T x, T y);
  48. /* returns the representative of the set containing x */
  49. inline T findSet(T x);
  50. /* returns main memory usage if the max nb of makeset calls is n */
  51. inline size_t mmusage(T n);
  52. };
  53. /************************************************************/
  54. template<class T>
  55. unionFind<T>::unionFind() {
  56. maxsize = UNION_INITIAL_SIZE;
  57. /* parent = new (long)[maxsize]; */
  58. parent = (T*)calloc(maxsize, sizeof(T));
  59. assert(parent);
  60. /* rank = new (long)[maxsize]; */
  61. rank = (T*)calloc(maxsize, sizeof(T));
  62. assert(rank);
  63. }
  64. /************************************************************/
  65. template<class T>
  66. unionFind<T>::~unionFind() {
  67. /* if (parent) delete [] parent;
  68. if (rank) delete [] rank;
  69. */
  70. if (parent) free(parent);
  71. if (rank) free(rank);
  72. }
  73. /************************************************************/
  74. /* return true if element x is in the structure */
  75. template<class T>
  76. inline bool
  77. unionFind<T>::inSet(T x) {
  78. if (x > 0 && x < maxsize && parent[x] > 0) {
  79. return true;
  80. } else {
  81. return false;
  82. }
  83. }
  84. /************************************************************/
  85. template<class T>
  86. void
  87. unionFind<T>::print() {
  88. for (T i=0; i< maxsize; i++) {
  89. if (parent[i] == 0) cout << "x ";
  90. else cout << parent[i] << " ";
  91. }
  92. cout << "\n";
  93. }
  94. /************************************************************/
  95. /*
  96. create a new set whose only member (and representative) is x; since x
  97. is disjoint we require x not be already in the set; */
  98. template<class T>
  99. inline void
  100. unionFind<T>::makeSet(T x) {
  101. /* cout << "makeSet " << x << "\n"; print(); */
  102. assert(x > 0);
  103. if (x >= maxsize) {
  104. /* reallocate parent */
  105. cout << "UnionFind::makeSet: reallocate double " << maxsize << "\n";
  106. parent = (T*)realloc(parent, 2*maxsize*sizeof(T));
  107. assert(parent);
  108. memset(parent + maxsize, 0, maxsize*sizeof(T));
  109. /*reallocate rank */
  110. rank = (T*)realloc(rank, 2*maxsize*sizeof(T));
  111. assert(rank);
  112. memset(rank + maxsize, 0, maxsize*sizeof(T));
  113. /*update maxsize */
  114. maxsize *= 2;
  115. }
  116. /*since x is disjoint we require x not be already in the set; should
  117. relax this..*/
  118. assert(!inSet(x));
  119. parent[x] = x;
  120. rank[x] = 0;
  121. }
  122. /************************************************************/
  123. /* returns the representative of the set containing x */
  124. template<class T>
  125. inline T
  126. unionFind<T>::findSet(T x) {
  127. /* valid entry */
  128. assert(inSet(x));
  129. if (parent[x] != x) {
  130. /* path compression heuristic */
  131. parent[x] = findSet(parent[x]);
  132. }
  133. /* parent[x] must be a root */
  134. assert(parent[parent[x]] == parent[x]);
  135. return parent[x];
  136. }
  137. /************************************************************/
  138. /* unites the dynamic sets that contain x and y; */
  139. template<class T>
  140. inline void
  141. unionFind<T>::makeUnion(T x, T y) {
  142. assert(inSet(x) && inSet(y));
  143. T setx = findSet(x);
  144. T sety = findSet(y);
  145. if (setx == sety) return;
  146. /* union by rank heuristic */
  147. assert(inSet(x) && inSet(y));
  148. if (rank[setx] > rank[sety]) {
  149. /* hook sety onto setx */
  150. parent[sety] = setx;
  151. } else {
  152. /* hook setx onto sety */
  153. parent[setx] = sety;
  154. /* if equal increase rank */
  155. if (sety == sety) {
  156. rank[sety]++;
  157. }
  158. }
  159. /* this does not have side effects.. */
  160. assert(findSet(x) == findSet(y));
  161. }
  162. /************************************************************/
  163. /* returns main memory usage if the max nb of makeset calls is n */
  164. template<class T>
  165. inline size_t
  166. unionFind<T>::mmusage(T n) {
  167. if (n < UNION_INITIAL_SIZE) n = UNION_INITIAL_SIZE;
  168. return (n * sizeof(T));
  169. }
  170. #endif