123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200 |
- /****************************************************************************
- *
- * MODULE: r.terraflow
- *
- * COPYRIGHT (C) 2007 Laura Toma
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- *****************************************************************************/
- #ifndef __UNION_FIND
- #define __UNION_FIND
- #include <assert.h>
- #include <stdlib.h>
- #include <string.h>
- #include <iostream>
- /* initial range guesstimate */
- #define UNION_INITIAL_SIZE 2000
- /* maintains a collection of disjoint dynamic sets; elements are in
- the range 1..maxsize-1 and range is increased dynamically; if element x
- is not in the set then parent[x] = 0;
- */
- template<class T>
- class unionFind {
- private:
- T* parent;
- T* rank;
- T maxsize;
-
- public:
- unionFind();
- ~unionFind();
-
- /* return true if element x is in the structure */
- inline bool inSet(T x);
- void print();
- /* create a new set whose only member (and representative) is x;
- since x is disjoint we require x not be already in the set; */
- inline void makeSet(T x);
-
- /* unites the dynamic sets that contain x and y; */
- inline void makeUnion(T x, T y);
-
- /* returns the representative of the set containing x */
- inline T findSet(T x);
-
- /* returns main memory usage if the max nb of makeset calls is n */
- inline size_t mmusage(T n);
- };
- /************************************************************/
- template<class T>
- unionFind<T>::unionFind() {
- maxsize = UNION_INITIAL_SIZE;
- /* parent = new (long)[maxsize]; */
- parent = (T*)calloc(maxsize, sizeof(T));
- assert(parent);
- /* rank = new (long)[maxsize]; */
- rank = (T*)calloc(maxsize, sizeof(T));
- assert(rank);
- }
- /************************************************************/
- template<class T>
- unionFind<T>::~unionFind() {
- /* if (parent) delete [] parent;
- if (rank) delete [] rank;
- */
- if (parent) free(parent);
- if (rank) free(rank);
- }
- /************************************************************/
- /* return true if element x is in the structure */
- template<class T>
- inline bool
- unionFind<T>::inSet(T x) {
- if (x > 0 && x < maxsize && parent[x] > 0) {
- return true;
- } else {
- return false;
- }
- }
- /************************************************************/
- template<class T>
- void
- unionFind<T>::print() {
- for (T i=0; i< maxsize; i++) {
- if (parent[i] == 0) cout << "x ";
- else cout << parent[i] << " ";
- }
- cout << "\n";
- }
- /************************************************************/
- /*
- create a new set whose only member (and representative) is x; since x
- is disjoint we require x not be already in the set; */
- template<class T>
- inline void
- unionFind<T>::makeSet(T x) {
- /* cout << "makeSet " << x << "\n"; print(); */
- assert(x > 0);
- if (x >= maxsize) {
- /* reallocate parent */
- cout << "UnionFind::makeSet: reallocate double " << maxsize << "\n";
- parent = (T*)realloc(parent, 2*maxsize*sizeof(T));
- assert(parent);
- memset(parent + maxsize, 0, maxsize*sizeof(T));
- /*reallocate rank */
- rank = (T*)realloc(rank, 2*maxsize*sizeof(T));
- assert(rank);
- memset(rank + maxsize, 0, maxsize*sizeof(T));
- /*update maxsize */
- maxsize *= 2;
- }
- /*since x is disjoint we require x not be already in the set; should
- relax this..*/
- assert(!inSet(x));
- parent[x] = x;
- rank[x] = 0;
- }
- /************************************************************/
- /* returns the representative of the set containing x */
- template<class T>
- inline T
- unionFind<T>::findSet(T x) {
- /* valid entry */
- assert(inSet(x));
- if (parent[x] != x) {
- /* path compression heuristic */
- parent[x] = findSet(parent[x]);
- }
- /* parent[x] must be a root */
- assert(parent[parent[x]] == parent[x]);
- return parent[x];
- }
- /************************************************************/
- /* unites the dynamic sets that contain x and y; */
- template<class T>
- inline void
- unionFind<T>::makeUnion(T x, T y) {
- assert(inSet(x) && inSet(y));
- T setx = findSet(x);
- T sety = findSet(y);
- if (setx == sety) return;
- /* union by rank heuristic */
- assert(inSet(x) && inSet(y));
- if (rank[setx] > rank[sety]) {
- /* hook sety onto setx */
- parent[sety] = setx;
- } else {
- /* hook setx onto sety */
- parent[setx] = sety;
- /* if equal increase rank */
- if (sety == sety) {
- rank[sety]++;
- }
- }
- /* this does not have side effects.. */
- assert(findSet(x) == findSet(y));
- }
- /************************************************************/
- /* returns main memory usage if the max nb of makeset calls is n */
- template<class T>
- inline size_t
- unionFind<T>::mmusage(T n) {
- if (n < UNION_INITIAL_SIZE) n = UNION_INITIAL_SIZE;
- return (n * sizeof(T));
- }
- #endif
|