depth1stiterator.h 8.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  1. #ifndef DEPTH1STITERATOR_H
  2. #define DEPTH1STITERATOR_H
  3. #include <iterator>
  4. #include <functional>
  5. #include <list>
  6. #include <set>
  7. #include <stack>
  8. /**
  9. * Graph searches provide the feature to colore nodes as they
  10. * are explored / visited.
  11. */
  12. enum NodeColor
  13. {
  14. /**
  15. * A node colored white means that it is not explored
  16. * by the search algorithm yet.
  17. */
  18. NC_WHITE = 0,
  19. /**
  20. * A node colored gray means that it has been noticed by
  21. * the search, but not exhaustively dealt with yet.
  22. */
  23. NC_GRAY,
  24. /**
  25. * A node has been explored exhaustively, that is all its
  26. * adjacents nodes are at least gray.
  27. */
  28. NC_BLACK
  29. };
  30. /**
  31. * A struct to decorate a node with color.
  32. */
  33. template<typename NODE>
  34. struct ColoredNode
  35. {
  36. NODE m_node;
  37. NodeColor m_color;
  38. ColoredNode()
  39. : m_color(NC_WHITE)
  40. {
  41. ;
  42. }
  43. ColoredNode(NODE node,
  44. NodeColor color)
  45. : m_node(node)
  46. , m_color(color)
  47. {
  48. ;
  49. }
  50. };
  51. template<typename NODE>
  52. bool operator==(const ColoredNode<NODE> & first,
  53. const ColoredNode<NODE> & second)
  54. {
  55. return first.m_node == second.m_node
  56. && first.m_color == second.m_color;
  57. }
  58. template<typename NODE>
  59. bool operator!=(const ColoredNode<NODE> & first,
  60. const ColoredNode<NODE> & second)
  61. {
  62. return first.m_node != second.m_node
  63. || first.m_color != second.m_color;
  64. }
  65. /**
  66. * Deapth1stIterator is an STL compliant forward iterator.
  67. *
  68. * Given a proper graph / node implementation, it is capable of
  69. * visiting the nodes (in depth-first manner). The visiting happens
  70. * in the manner of iteration.
  71. *
  72. * The value type of this iterator is *not* node, but colored node.
  73. * One can iterate nodes in a preorder manner, that is, a node
  74. * is given to the iterating client before its adjacents are explored
  75. * (accompanying color will be gray).
  76. *
  77. * One can iterate npodes in postorder manner, that is, a node
  78. * is given to the iterating client after its adjacents are
  79. * explored (accompanying color will be black).
  80. *
  81. * One can configure this iterator to emit the same node both before
  82. * (with gray color) and after (with black color) its adjacents are
  83. * explored.
  84. *
  85. * Concepts required by Depth1stIterator.
  86. *
  87. * GRAPH:
  88. * o should implement syntax "graph.getAdjacents(node, OUTITER);"
  89. * with an arbitrary output iterator given. The method should
  90. * give all adjacents of node through OUTITER.
  91. *
  92. *
  93. * NODE:
  94. * o Default Constructible
  95. * o Assignable
  96. * o Equality Comparable
  97. */
  98. template<typename GRAPH,
  99. typename NODE,
  100. typename COMPARE = std::less<NODE> >
  101. class Depth1stIterator : public std::iterator<std::forward_iterator_tag, ColoredNode<NODE> >
  102. {
  103. public:
  104. //
  105. // public types
  106. //
  107. typedef GRAPH Graph;
  108. typedef NODE Node;
  109. typedef ColoredNode<NODE> CNode;
  110. /**
  111. * Flags to control when we should meet an item
  112. * during iteration. Before visiting its adjacents
  113. * (pre visit), after visiting its adjacents (post
  114. * visit). You can combine them with bitwise or
  115. * to receive the items both before and after.
  116. */
  117. enum Flag
  118. {
  119. /**
  120. * The value of PreVisit coincides with the value of
  121. * NC_GRAY. It's not a coincidence. They are actually the
  122. * same thing, but used in different context / sentences.
  123. */
  124. PreVisit = 1,
  125. /**
  126. * The value of PostVisit coincides with the value of
  127. * NC_BLACK. It's not a coincidence. They are actually the
  128. * same thing, but used in different context / sentences.
  129. */
  130. PostVisit = 2
  131. };
  132. private:
  133. //
  134. // private members
  135. //
  136. Graph * m_graph;
  137. std::stack<CNode> m_nodesToVisit;
  138. std::set<Node, COMPARE> m_visitedNodes;
  139. CNode m_currentNode;
  140. int m_flags;
  141. public:
  142. //
  143. // public operators
  144. //
  145. /**
  146. * Constructs an "end" iterator.
  147. */
  148. Depth1stIterator()
  149. : m_graph(NULL)
  150. {
  151. ;
  152. }
  153. /**
  154. * Constructs a "begin" iterator that iterates through elements in
  155. * a depth-first search manner, starting with a single node.
  156. */
  157. Depth1stIterator(Graph & graph,
  158. NODE node,
  159. int flags = PreVisit)
  160. : m_graph(&graph)
  161. , m_flags(flags)
  162. {
  163. m_nodesToVisit.push(CNode(node,
  164. NC_GRAY));
  165. next();
  166. }
  167. /**
  168. * Constructs a "begin" iterator that iterates through elements
  169. * in depth-first search manner, starting with all the nodes
  170. * given here via the input iterators.
  171. */
  172. template<typename NODE_IITER>
  173. Depth1stIterator(Graph & graph,
  174. NODE_IITER first,
  175. NODE_IITER last,
  176. int flags = PreVisit)
  177. : m_graph(&graph)
  178. , m_flags(flags)
  179. {
  180. for (; first != last; ++first)
  181. {
  182. m_nodesToVisit.push(CNode(*first,
  183. NC_GRAY));
  184. }
  185. next();
  186. }
  187. CNode operator*()
  188. {
  189. return m_currentNode;
  190. }
  191. CNode * operator->()
  192. {
  193. return &m_currentNode;
  194. }
  195. Depth1stIterator & operator++()
  196. {
  197. next();
  198. return *this;
  199. }
  200. Depth1stIterator operator++(int)
  201. {
  202. Depth1stIterator
  203. rv(*this);
  204. next();
  205. return rv;
  206. }
  207. private:
  208. //
  209. // implementation details
  210. //
  211. bool allowedColor(NodeColor color) const
  212. {
  213. bool
  214. rv = static_cast<bool>(m_flags & (static_cast<int>(color)));
  215. return rv;
  216. }
  217. #define __yield_return(cn) {if(allowedColor(cn.m_color))return;}
  218. void next()
  219. {
  220. if (m_graph == NULL)
  221. return;
  222. while (!m_nodesToVisit.empty())
  223. {
  224. m_currentNode = m_nodesToVisit.top();
  225. if (m_currentNode.m_color == NC_BLACK)
  226. {
  227. m_nodesToVisit.pop();
  228. }
  229. else // NC_GRAY
  230. {
  231. m_nodesToVisit.top().m_color = NC_BLACK;
  232. std::list<Node>
  233. adjacents;
  234. m_graph->getAdjacents(m_currentNode.m_node,
  235. std::inserter(adjacents,
  236. adjacents.end()));
  237. typename std::list<Node>::const_reverse_iterator
  238. it = adjacents.rbegin(),
  239. end = adjacents.rend();
  240. for (; it != end; ++it)
  241. {
  242. Node
  243. adjacent = *it;
  244. if (m_visitedNodes.find(adjacent) == m_visitedNodes.end())
  245. {
  246. m_visitedNodes.insert(adjacent);
  247. m_nodesToVisit.push(CNode(adjacent,
  248. NC_GRAY));
  249. }
  250. }
  251. }
  252. __yield_return(m_currentNode);
  253. }
  254. m_graph = NULL;
  255. }
  256. #undef __yield_return
  257. template<typename G,
  258. typename N,
  259. typename C>
  260. friend bool operator==(const Depth1stIterator<G, N, C> & first,
  261. const Depth1stIterator<G, N, C> & second);
  262. template<typename G,
  263. typename N,
  264. typename C>
  265. friend bool operator!=(const Depth1stIterator<G, N, C> & first,
  266. const Depth1stIterator<G, N, C> & second);
  267. };
  268. template<typename GRAPH,
  269. typename NODE,
  270. typename COMPARE>
  271. bool operator==(const Depth1stIterator<GRAPH, NODE, COMPARE> & first,
  272. const Depth1stIterator<GRAPH, NODE, COMPARE> & second)
  273. {
  274. bool
  275. rv(false);
  276. if (first.m_graph == NULL && second.m_graph == NULL)
  277. {
  278. rv = true;
  279. }
  280. else
  281. {
  282. rv = first.m_graph == second.m_graph
  283. && first.m_flags == second.m_flags
  284. && first.m_currentNode == second.m_currentNode
  285. && first.m_nodesToVisit == second.m_nodesToVisit
  286. && first.m_visitedNodes == second.m_visitedNodes;
  287. }
  288. return rv;
  289. }
  290. template<typename GRAPH,
  291. typename NODE,
  292. typename COMPARE>
  293. bool operator!=(const Depth1stIterator<GRAPH, NODE, COMPARE> & first,
  294. const Depth1stIterator<GRAPH, NODE, COMPARE> & second)
  295. {
  296. return !(first == second);
  297. }
  298. #endif // DEPTH1STITERATOR_H