unionFind.h 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  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. /* initial range guesstimate */
  25. #define UNION_INITIAL_SIZE 2000
  26. /* maintains a collection of disjoint dynamic sets; elements are in
  27. the range 1..maxsize-1 and range is increased dynamically; if element x
  28. is not in the set then parent[x] = 0;
  29. */
  30. template<class T>
  31. class unionFind {
  32. private:
  33. T* parent;
  34. T* rank;
  35. T maxsize;
  36. public:
  37. unionFind();
  38. ~unionFind();
  39. /* return true if element x is in the structure */
  40. inline bool inSet(T x);
  41. void print();
  42. /* create a new set whose only member (and representative) is x;
  43. since x is disjoint we require x not be already in the set; */
  44. inline void makeSet(T x);
  45. /* unites the dynamic sets that contain x and y; */
  46. inline void makeUnion(T x, T y);
  47. /* returns the representative of the set containing x */
  48. inline T findSet(T x);
  49. /* returns main memory usage if the max nb of makeset calls is n */
  50. inline size_t mmusage(T n);
  51. };
  52. /************************************************************/
  53. template<class T>
  54. unionFind<T>::unionFind() {
  55. maxsize = UNION_INITIAL_SIZE;
  56. /* parent = new (long)[maxsize]; */
  57. parent = (T*)calloc(maxsize, sizeof(T));
  58. assert(parent);
  59. /* rank = new (long)[maxsize]; */
  60. rank = (T*)calloc(maxsize, sizeof(T));
  61. assert(rank);
  62. }
  63. /************************************************************/
  64. template<class T>
  65. unionFind<T>::~unionFind() {
  66. /* if (parent) delete [] parent;
  67. if (rank) delete [] rank;
  68. */
  69. if (parent) free(parent);
  70. if (rank) free(rank);
  71. }
  72. /************************************************************/
  73. /* return true if element x is in the structure */
  74. template<class T>
  75. inline bool
  76. unionFind<T>::inSet(T x) {
  77. if (x > 0 && x < maxsize && parent[x] > 0) {
  78. return true;
  79. } else {
  80. return false;
  81. }
  82. }
  83. /************************************************************/
  84. template<class T>
  85. void
  86. unionFind<T>::print() {
  87. for (T i=0; i< maxsize; i++) {
  88. if (parent[i] == 0) cout << "x ";
  89. else cout << parent[i] << " ";
  90. }
  91. cout << "\n";
  92. }
  93. /************************************************************/
  94. /*
  95. create a new set whose only member (and representative) is x; since x
  96. is disjoint we require x not be already in the set; */
  97. template<class T>
  98. inline void
  99. unionFind<T>::makeSet(T x) {
  100. /* cout << "makeSet " << x << "\n"; print(); */
  101. assert(x > 0);
  102. if (x >= maxsize) {
  103. /* reallocate parent */
  104. cout << "UnionFind::makeSet: reallocate double " << maxsize << "\n";
  105. parent = (T*)realloc(parent, 2*maxsize*sizeof(T));
  106. assert(parent);
  107. memset(parent + maxsize, 0, maxsize*sizeof(T));
  108. /*reallocate rank */
  109. rank = (T*)realloc(rank, 2*maxsize*sizeof(T));
  110. assert(rank);
  111. memset(rank + maxsize, 0, maxsize*sizeof(T));
  112. /*update maxsize */
  113. maxsize *= 2;
  114. }
  115. /*since x is disjoint we require x not be already in the set; should
  116. relax this..*/
  117. assert(!inSet(x));
  118. parent[x] = x;
  119. rank[x] = 0;
  120. }
  121. /************************************************************/
  122. /* returns the representative of the set containing x */
  123. template<class T>
  124. inline T
  125. unionFind<T>::findSet(T x) {
  126. /* valid entry */
  127. assert(inSet(x));
  128. if (parent[x] != x) {
  129. /* path compression heuristic */
  130. parent[x] = findSet(parent[x]);
  131. }
  132. /* parent[x] must be a root */
  133. assert(parent[parent[x]] == parent[x]);
  134. return parent[x];
  135. }
  136. /************************************************************/
  137. /* unites the dynamic sets that contain x and y; */
  138. template<class T>
  139. inline void
  140. unionFind<T>::makeUnion(T x, T y) {
  141. assert(inSet(x) && inSet(y));
  142. T setx = findSet(x);
  143. T sety = findSet(y);
  144. if (setx == sety) return;
  145. /* union by rank heuristic */
  146. assert(inSet(x) && inSet(y));
  147. if (rank[setx] > rank[sety]) {
  148. /* hook sety onto setx */
  149. parent[sety] = setx;
  150. } else {
  151. /* hook setx onto sety */
  152. parent[setx] = sety;
  153. /* if equal increase rank */
  154. if (sety == sety) {
  155. rank[sety]++;
  156. }
  157. }
  158. /* this does not have side effects.. */
  159. assert(findSet(x) == findSet(y));
  160. }
  161. /************************************************************/
  162. /* returns main memory usage if the max nb of makeset calls is n */
  163. template<class T>
  164. inline size_t
  165. unionFind<T>::mmusage(T n) {
  166. if (n < UNION_INITIAL_SIZE) n = UNION_INITIAL_SIZE;
  167. return (n * sizeof(T));
  168. }
  169. #endif