Aleph-w  1.9
General library for algorithms and data structures
tpl_spanning_tree.H
1 
2 /* Aleph-w
3 
4  / \ | | ___ _ __ | |__ __ __
5  / _ \ | |/ _ \ '_ \| '_ \ ____\ \ /\ / / Data structures & Algorithms
6  / ___ \| | __/ |_) | | | |_____\ V V / version 1.9b
7  /_/ \_\_|\___| .__/|_| |_| \_/\_/ https://github.com/lrleon/Aleph-w
8  |_|
9 
10  This file is part of Aleph-w library
11 
12  Copyright (c) 2002-2018 Leandro Rabindranath Leon & Alejandro Mujica
13 
14  This program is free software: you can redistribute it and/or modify
15  it under the terms of the GNU General Public License as published by
16  the Free Software Foundation, either version 3 of the License, or
17  (at your option) any later version.
18 
19  This program is distributed in the hope that it will be useful, but
20  WITHOUT ANY WARRANTY; without even the implied warranty of
21  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
22  General Public License for more details.
23 
24  You should have received a copy of the GNU General Public License
25  along with this program. If not, see <https://www.gnu.org/licenses/>.
26 */
27 # ifndef TPL_SPANNING_TREE_H
28 # define TPL_SPANNING_TREE_H
29 
30 # include <tpl_graph.H>
31 
32 namespace Aleph {
33 
34 
53  template <class GT, class SA = Dft_Show_Arc<GT> >
55 {
56  SA sa;
57  GT * gptr = nullptr;
58  GT * tptr = nullptr;
59 
60  bool build_tree(typename GT::Node * gnode, typename GT::Arc * garc,
61  typename GT::Node * tnode)
62  {
63  NODE_BITS(gnode).set_bit(Spanning_Tree, true); // marcar nodo
64  ARC_BITS(garc).set_bit(Spanning_Tree, true); // marcar arco
65 
66  auto tree_tgt_node = tptr->insert_node(gnode->get_info());
67  GT::map_nodes(gnode, tree_tgt_node);
68 
69  auto tarc = tptr->insert_arc(tnode, tree_tgt_node, garc->get_info());
70  GT::map_arcs(garc, tarc);
71 
72  tnode = tree_tgt_node;
73  if (tptr->get_num_nodes() == gptr->get_num_nodes()) // ¿grafo abarcado?
74  return true; // tree ya contiene el árbol abarcador
75 
76  assert(tptr->get_num_nodes() > tptr->get_num_arcs()); // debe ser acíclico
77 
78  for (Node_Arc_Iterator<GT, SA> i(gnode, sa);
79  i.has_curr() and tptr->get_num_nodes() < gptr->get_num_nodes();
80  i.next_ne())
81  {
82  auto arc = i.get_current_arc_ne();
83  if (IS_ARC_VISITED(arc, Spanning_Tree))
84  continue;
85 
86  auto arc_tgt_node = i.get_tgt_node();
87  if (IS_NODE_VISITED(arc_tgt_node, Spanning_Tree))
88  continue; // destino ya visitado desde otro arco
89 
90  if (build_tree(arc_tgt_node, arc, tnode))
91  return false;
92  }
93 
94  return false;
95  }
96 
97  bool build_tree(GT & g, typename GT::Node * gnode, GT & tree)
98  {
99  gptr = &g;
100  tptr = &tree;
101 
102  gptr->reset_nodes();
103  gptr->reset_arcs();
104 
105  clear_graph(*tptr); // asegurar que árbol destino esté vacío
106 
107  NODE_BITS(gnode).set_bit(Spanning_Tree, true); // marcar gnode
108 
109  auto tnode = tree.insert_node(gnode->get_info());
110  GT::map_nodes(gnode, tnode);
111 
112  for (Node_Arc_Iterator<GT, SA> i(gnode, sa);
113  i.has_curr() and tptr->get_num_nodes() < gptr->get_num_nodes();
114  i.next_ne())
115  {
116  auto arc = i.get_current_arc_ne();
117  if (IS_ARC_VISITED(arc, Spanning_Tree))
118  continue;
119 
120  auto arc_tgt_node = i.get_tgt_node();
121  if (IS_NODE_VISITED(arc_tgt_node, Spanning_Tree))
122  continue; // destino ya visitado desde otro arco
123 
124  if (build_tree(arc_tgt_node, arc, tnode))
125  return false;
126  }
127 
128  return true;
129  }
130 
131 public:
132 
133  Find_Depth_First_Spanning_Tree(SA __sa = SA()) : sa(__sa) { /* empty */ }
134 
155  typename GT::Node * operator () (GT & g, GT & tree)
156  {
157  auto start = g.get_first_node();
158  if (not build_tree(g, start, tree))
159  return nullptr;
160 
161  return start;
162  }
163 
188  typename GT::Node * operator () (GT & g, typename GT::Node * gnode, GT & tree)
189  {
190  this->build_tree(g, gnode, tree);
191  return (typename GT::Node *) NODE_COOKIE(gnode);
192  }
193 };
194 
195 
196 
219  template <class GT, class SA = Dft_Show_Arc<GT> >
221 {
222  SA & sa;
223 
224  void build_tree(GT & g, typename GT::Node * gp, GT & tree)
225  {
226  g.reset_bit_nodes(Spanning_Tree);
227  g.reset_bit_arcs(Spanning_Tree);
228 
229  clear_graph(tree);
230 
231  unique_ptr<typename GT::Node> tp_auto(new typename GT::Node(gp));
232  tree.insert_node(tp_auto.get());
233  GT::map_nodes(gp, tp_auto.release());
234 
235  DynListQueue<typename GT::Arc*> q; // insertar en cola arcos gp
236  for (Node_Arc_Iterator<GT, SA> i(gp, sa); i.has_curr(); i.next_ne())
237  q.put(i.get_current_arc_ne());
238 
239  NODE_BITS(gp).set_bit(Spanning_Tree, true);
240 
241  while (not q.is_empty())
242  {
243  auto garc = q.get();
244  ARC_BITS(garc).set_bit(Spanning_Tree, true);
245  auto gsrc = g.get_src_node(garc);
246  auto gtgt = g.get_tgt_node(garc);
247 
248  if (IS_NODE_VISITED(gsrc, Spanning_Tree) and
249  IS_NODE_VISITED(gtgt, Spanning_Tree))
250  continue; // los dos nodos de garc ya fueron visitados
251 
252  if (IS_NODE_VISITED(gtgt, Spanning_Tree)) // ¿gtgt visitado?
253  std::swap(gsrc, gtgt); // sí, intercámbielo con gsrc
254 
255  auto tsrc = mapped_node<GT>(gsrc);
256  NODE_BITS(gtgt).set_bit(Spanning_Tree, true); // gtgt visitado
257 
258  // crear copia de gtgt, insertarlo en tree y mapearlo
259  unique_ptr<typename GT::Node> ttgt_auto(new typename GT::Node(gtgt));
260  tree.insert_node(ttgt_auto.get());
261  auto ttgt = ttgt_auto.release();
262  GT::map_nodes(gtgt, ttgt);
263 
264  // insertar nuevo arco en tree y mapearlo
265  auto tarc = tree.insert_arc(tsrc, ttgt, garc->get_info());
266  GT::map_arcs(garc, tarc);
267  if (tree.get_num_nodes() == g.get_num_nodes()) // ¿abarca a g?
268  break;
269 
270  // insertar en cola arcos de gtgt
271  for (Node_Arc_Iterator<GT, SA> i(gtgt, sa); i.has_curr(); i.next_ne())
272  {
273  auto current_arc = i.get_current_arc_ne();
274  if (IS_ARC_VISITED(current_arc, Spanning_Tree))
275  continue;
276 
277  // revise nodos de arcos para ver si han sido visitados
278  if (IS_NODE_VISITED(g.get_src_node(current_arc), Spanning_Tree) and
279  IS_NODE_VISITED(g.get_tgt_node(current_arc), Spanning_Tree))
280  continue; // nodos ya visitados ==> no meter arco
281  q.put(current_arc);
282  }
283  }
284  }
285 
286 public:
287 
288  Find_Breadth_First_Spanning_Tree(SA && __sa = SA()) : sa(__sa) { /* empty */ }
289 
290  Find_Breadth_First_Spanning_Tree(SA & __sa) : sa(__sa) { /* empty */ }
291 
311  void operator () (GT & g, typename GT::Node * gnode, GT & tree)
312  {
313  find_breadth_first_spanning_tree <GT, SA> (g, gnode, tree);
314  }
315  };
316 
317 
326  template <class GT>
328 {
329 public:
330 
345  {
346  return build_spanning_tree(arcs);
347  }
348 };
349 
350 
351 } // end namespace Aleph
352 
353 # endif // TPL_SPANNING_TREE_H
void clear_graph(GT &g) noexcept
Definition: tpl_graph.H:3463
GT::Node * operator()(GT &g, GT &tree)
Definition: tpl_spanning_tree.H:155
#define NODE_COOKIE(p)
Definition: aleph-graph.H:333
GT build_spanning_tree(const DynArray< typename GT::Arc *> &arcs)
Definition: tpl_graph_utils.H:1115
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:327
Definition: tpl_dynListQueue.H:50
void map_arcs(typename GTS::Arc *p, typename GTT::Arc *q) noexcept
Definition: tpl_graph.H:3445
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:360
DynList< typename GT::Arc * > arcs(typename GT::Node *p, SA sa=SA())
Definition: tpl_graph.H:1893
void map_nodes(typename GTS::Node *p, typename GTT::Node *q) noexcept
Definition: tpl_graph.H:3419
Definition: ah-comb.H:35
Definition: tpl_spanning_tree.H:54
#define NODE_BITS(p)
Definition: aleph-graph.H:305
#define ARC_BITS(p)
Definition: aleph-graph.H:351
Definition: tpl_dynArray.H:159
Definition: tpl_spanning_tree.H:327
Definition: tpl_spanning_tree.H:220
Definition: tpl_graph.H:1177
T & put(const T &data)
The type of element.
Definition: tpl_dynListQueue.H:125

Leandro Rabindranath León