Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
Prim.H
1 # ifndef PRIM_H
2 # define PRIM_H
3 
4 # include <tpl_agraph.H>
5 # include <tpl_graph_utils.H>
6 # include <archeap.H>
7 
8 namespace Aleph {
9 
10 using namespace Aleph;
11 
12  template <class GT>
13 struct Prim_Info
14 {
15  typename GT::Node * tree_node; // imagen en el árbol abarcador
16  void * heap_node; // puntero en el heap exclusivo
17 
18  Prim_Info() : tree_node(NULL), heap_node(NULL) { /* empty */ }
19 };
20 
21 # define PRIMINFO(p) static_cast<Prim_Info<GT>*>(NODE_COOKIE(p))
22 # define TREENODE(p) (PRIMINFO(p)->tree_node)
23 # define HEAPNODE(p) (PRIMINFO(p)->heap_node)
24 
25  template <class GT, class Distance>
27 {
28  typedef typename ArcHeap<GT, Distance, Prim_Heap_Info>::Node Node;
29 
30  Node *& operator () (typename GT::Node * p)
31  {
32  return (Node*&) HEAPNODE(p);
33  }
34 };
35 
36  template <class GT, class Distance>
38 {
39  typedef typename ArcHeap<GT, Distance, Simple_Prim_Heap>::Node Node;
40 
41  Node *& operator () (typename GT::Node * p)
42  {
43  return (Node*&) NODE_COOKIE(p);
44  }
45 };
46 
47  template <class GT>
49 {
50  GT & tree;
51 
52  Init_Prim_Info(GT & __tree) : tree(__tree) { /* empty */ }
53 
54  void operator () (GT & g, typename GT::Node * p)
55  {
56  g.reset_bit(p, Aleph::Prim);
57  NODE_COOKIE(p) = new Prim_Info<GT>;
58  TREENODE(p) = tree.insert_node(p->get_info());
59  }
60 };
61 
62  template <class GT>
64 {
65  void operator () (GT &, typename GT::Node * p)
66  {
67  Prim_Info<GT> * aux = PRIMINFO(p);
68  GT::map_nodes(p, TREENODE(p));
69  delete aux;
70  }
71 };
72 
73 
116  template <class GT,
117  class Distance = Dft_Dist<GT>,
118  class SA = Dft_Show_Arc<GT> >
120 {
122 
124 
126 
128 
129  Distance & dist;
130  SA & sa;
131 
132 public:
133 
140  Prim_Min_Spanning_Tree(Distance && __dist = Distance(),
141  SA && __sa = SA())
142  : dist(__dist), sa(__sa)
143  {
144  // empty
145  }
146 
147  Prim_Min_Spanning_Tree(Distance & __dist, SA & __sa)
148  : dist(__dist), sa(__sa)
149  {
150  // empty
151  }
152 
153 private:
154 
155  void paint_min_spanning_tree(GT & g, typename GT::Node * first)
156  {
157  if (g.is_digraph())
158  throw std::domain_error("g is a digraph");
159 
160  g.reset_nodes();
161  g.reset_arcs();
162 
163  NODE_BITS(first).set_bit(Aleph::Prim, true); // visitado
164 
165  Simple_Heap heap(dist, Acc_Simple_Heap());
166  for (Out_Iterator<GT, SA> it(first, sa); it.has_curr(); it.next())
167  {
168  typename GT::Arc * arc = it.get_current_arc();
169  heap.put_arc(arc, it.get_tgt_node());
170  }
171 
172  const size_t V1 = g.get_num_nodes() - 1;
173  size_t count = 0;
174 
175  while (count < V1 and not heap.is_empty())
176  { // obtenga siguiente menor arco
177  typename GT::Arc * min_arc = heap.get_min_arc();
178  if (IS_ARC_VISITED(min_arc, Aleph::Prim))
179  continue;
180 
181  ARC_BITS(min_arc).set_bit(Aleph::Prim, true);
182 
183  typename GT::Node * src = g.get_src_node(min_arc);
184  typename GT::Node * tgt = g.get_tgt_node(min_arc);
185  if (IS_NODE_VISITED(src, Aleph::Prim) and
186  IS_NODE_VISITED(tgt, Aleph::Prim))
187  continue; // este arco cerraría un ciclo en el árbol
188 
189  typename GT::Node * tgt_node =
190  IS_NODE_VISITED(src, Aleph::Prim) ? tgt : src;
191 
192  NODE_BITS(tgt_node).set_bit(Aleph::Prim, true);
193 
194  // insertar en heap arcos no visitados de tgt_node
195  for (Out_Iterator<GT, SA> it(tgt_node, sa); it.has_curr(); it.next())
196  {
197  typename GT::Arc * arc = it.get_current_arc();
198  if (IS_ARC_VISITED(arc, Aleph::Prim))
199  continue;
200 
201  typename GT::Node * tgt = it.get_tgt_node();
202  if (IS_NODE_VISITED(tgt, Aleph::Prim))
203  continue; // nodo visitado ==> causará ciclo
204 
205  heap.put_arc(arc, tgt);
206  }
207 
208  ++count;
209  ARC_BITS(min_arc).set_bit(Aleph::Prim, true);
210  }
211  }
212 
213  void min_spanning_tree(GT & g, typename GT::Node * first, GT & tree)
214  {
215  if (g.is_digraph())
216  throw std::domain_error("g is a digraph");
217 
218  clear_graph(tree);
219 
220  Init_Prim_Info <GT> init(tree);
222 
223  NODE_BITS(first).set_bit(Aleph::Prim, true); // visitado
224 
225  Heap heap(dist, Acc_Heap()) ;
226  // meter en heap arcos iniciales del primer nodo
227  for (Out_Iterator<GT, SA> it(first, sa); it.has_curr(); it.next())
228  {
229  typename GT::Arc * arc = it.get_current_arc();
230  heap.put_arc(arc, it.get_tgt_node());
231  }
232 
233  const size_t V1 = g.get_num_nodes() - 1;
234 
235  while (tree.get_num_arcs() < V1 and not heap.is_empty())
236  { // obtenga siguiente menor arco
237  typename GT::Arc * min_arc = heap.get_min_arc();
238  if (IS_ARC_VISITED(min_arc, Aleph::Prim))
239  continue;
240 
241  ARC_BITS(min_arc).set_bit(Aleph::Prim, true);
242 
243  typename GT::Node * src = g.get_src_node(min_arc);
244  typename GT::Node * tgt = g.get_tgt_node(min_arc);
245  if (IS_NODE_VISITED(src, Aleph::Prim) and
246  IS_NODE_VISITED(tgt, Aleph::Prim))
247  continue; // este arco cerraría un ciclo en el árbol
248 
249  typename GT::Node * tgt_node =
250  IS_NODE_VISITED(src, Aleph::Prim) ? tgt : src;
251 
252  NODE_BITS(tgt_node).set_bit(Aleph::Prim, true);
253 
254  // insertar en heap arcos no visitados de tgt_node
255  for (Out_Iterator<GT, SA> it(tgt_node, sa); it.has_curr(); it.next())
256  {
257  typename GT::Arc * arc = it.get_current_arc();
258  if (IS_ARC_VISITED(arc, Aleph::Prim))
259  continue;
260 
261  typename GT::Node * tgt = it.get_tgt_node();
262  if (IS_NODE_VISITED(tgt, Aleph::Prim))
263  continue; // nodo visitado ==> causará ciclo
264 
265  heap.put_arc(arc, tgt);
266  }
267 
268  // insertar nuevo arco en tree y mapearlo
269  typename GT::Arc * tree_arc =
270  tree.insert_arc(TREENODE(src), TREENODE(tgt), min_arc->get_info());
271  GT::map_arcs(min_arc, tree_arc);
272  }
273 
275  }
276 
277 public:
278 
291  void operator () (GT & g, GT & tree)
292  {
293  min_spanning_tree(g, g.get_first_node(), tree);
294  }
295 
309  void operator () (GT & g, typename GT::Node * start, GT & tree)
310  {
311  min_spanning_tree(g, start, tree);
312  }
313 
315  void operator () (GT & g)
316  {
317  paint_min_spanning_tree(g, g.get_first_node());
318  }
319 
320  void operator () (GT & g, typename GT::Node * start)
321  {
322  paint_min_spanning_tree(g, start);
323  }
324 };
325 
326 
327 
328 # undef HEAPNODE
329 # undef TREENODE
330 # undef PRIMINFO
331 } // end namespace Aleph
332 
333 # endif // PRIM_H
Itor::difference_type count(const Itor &beg, const Itor &end, const T &value)
Definition: ahAlgo.H:127
Definition: Prim.H:13
#define NODE_COOKIE(p)
Definition: aleph-graph.H:248
Definition: Prim.H:48
Definition: tpl_graph.H:1389
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:242
Definition: Prim.H:63
Prim_Min_Spanning_Tree(Distance &&__dist=Distance(), SA &&__sa=SA())
Definition: Prim.H:140
Definition: Prim.H:37
void clear_graph(GT &g)
Definition: tpl_graph.H:2486
#define IS_ARC_VISITED(p, bit)
Definition: aleph-graph.H:275
Definition: tpl_graph.H:1186
Definition: Prim.H:26
Definition: tpl_graph.H:634
void next()
Adelanta el iterador una posición.
Definition: filter_iterator.H:143
#define NODE_BITS(p)
Definition: aleph-graph.H:221
Definition: Prim.H:119
Definition: tpl_graph_utils.H:2291
#define ARC_BITS(p)
Definition: aleph-graph.H:266
Definition: archeap.H:10
void operator()(GT &g, GT &tree)
Definition: Prim.H:291

Leandro Rabindranath León