Aleph-w  1.5a.2
Biblioteca general de algoritmos y estructuras de datos
 Todo Clases Archivos Funciones Variables 'typedefs' Enumeraciones Amigas Grupos Páginas
topological_sort.H
1 # ifndef TOPOLOGICAL_SORT_H
2 # define TOPOLOGICAL_SORT_H
3 
4 # include <tpl_dynListQueue.H>
5 # include <tpl_graph.H>
6 
7 namespace Aleph {
8 
9 
18  template <class GT, class SA = Dft_Show_Arc<GT> >
20 {
21  SA & sa;
22  GT * gptr;
23 
24 public:
25 
26  Topological_Sort(SA && __sa = SA()) : sa(__sa), gptr(NULL) { /* empty */ }
27 
28  Topological_Sort(SA & __sa) : sa(__sa), gptr(NULL) { /* empty */ }
29 
30 private:
31 
32  template <template <class> class List>
33  void topological_sort(typename GT::Node * curr,
34  List<typename GT::Node*> & list)
35  {
36  I(gptr != NULL);
37 
38  if (IS_NODE_VISITED(curr, Depth_First))
39  return;
40 
41  NODE_BITS(curr).set_bit(Depth_First, 1); // marcarlo como visitado
42 
43  const size_t & n = gptr->get_num_nodes();
44 
45  // visitar recursivamente en sufijo los nodos adyacentes a curr
46  for (Out_Iterator<GT, SA> it(curr, sa);
47  it.has_curr() and list.size() < n; it.next())
48  topological_sort(it.get_tgt_node(), list);
49 
50  list.insert(curr); // inserción sufija de nodo que devino sumidero
51  }
52 
53 public:
54 
65  template <template <class> class List>
66  List<typename GT::Node*> perform (GT & g)
67  {
68  if (not g.is_digraph())
69  throw std::domain_error("g is not a digraph");
70 
71  g.reset_bit_nodes(Depth_First); // iniciar bit de marca de visita en nodos
72 
73  gptr = &g;
74  List<typename GT::Node*> list;
75 
76  // recorrer todos los nodos
77  const size_t & n = gptr->get_num_nodes();
78  for (typename GT::Node_Iterator it(g); it.has_curr() and list.size() < n;
79  it.next())
80  {
81  typename GT::Node * curr = it.get_current_node();
82  if (not IS_NODE_VISITED(curr, Depth_First))
83  topological_sort(curr, list);
84  }
85 
86  return list;
87  }
88 
92  {
93  perform<DynDlist>(g).swap(list);
94  }
95 };
96 
106  template <class GT, class SA = Dft_Show_Arc<GT> >
108 {
109  SA & sa;
110 
111 public:
112 
113  Q_Topological_Sort(SA && __sa = SA()) : sa(__sa) { /* empty */ }
114 
115  Q_Topological_Sort(SA & __sa) : sa(__sa) { /* empty */ }
116 
128  template <template <class> class List>
129  List<typename GT::Node*> perform (GT & g)
130  {
131  if (not g.is_digraph())
132  throw std::domain_error("g is not a digraph");
133 
134  g.reset_counter_nodes();
135 
136  List<typename GT::Node*> list;
137 
138  // recorra todos los arcos y contar grados de entrada
139  for (Arc_Iterator<GT,SA> it(g, sa); it.has_curr(); it.next())
140  NODE_COUNTER(it.get_tgt_node())++;
141 
142  // buscar nodos con grado de entrada 0 y meterlos en cola
143  DynListQueue<typename GT::Node*> q; // cola de fuentes
144  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next())
145  {
146  typename GT::Node * p = it.get_current_node();
147  if (NODE_COUNTER(p) == 0) // ¿es un nodo fuente?
148  q.put(p); // sí ==> colocarlo en la cola
149  }
150 
151  while (not q.is_empty())
152  {
153  typename GT::Node * p = q.get(); // saque último fuente
154 
155  I(NODE_COUNTER(p) == 0);
156 
157  list.append(p); // insértelo en el orden topológico
158 
159  // decrementar grado de entrada de cada nodo adyacente a p
160  for (Out_Iterator<GT, SA> it(p, sa); it.has_curr(); it.next())
161  {
162  typename GT::Node * tgt = it.get_tgt_node();
163  if (--NODE_COUNTER(tgt) == 0) // ¿tgt deviene fuente?
164  q.put(tgt); // sí ==> colóquelo en la cola
165  }
166  }
167 
168  return list;
169  }
170 
183  template <template <class> class RankList = DynDlist,
184  template <class> class List = DynList>
185  RankList<List<typename GT::Node*>> ranks(GT & g)
186  {
187  if (not g.is_digraph())
188  throw std::domain_error("g is not a digraph");
189 
190  g.reset_counter_nodes();
191 
192  // recorra todos los nodos para contabilizar grado de entrada
193  for (typename GT::Node_Iterator i(g); i.has_curr(); i.next())
194  for (Node_Arc_Iterator <GT, SA> j(i.get_current_node(), sa);
195  j.has_curr(); j.next())
196  NODE_COUNTER(j.get_tgt_node())++;
197 
198  // revisar nodos con grado de entrada 0 y meterlos en cola
199  DynListQueue<typename GT::Node*> q; // cola de fuentes
200  for (typename GT::Node_Iterator it(g); it.has_curr(); it.next())
201  {
202  typename GT::Node * p = it.get_current_node();
203  if (NODE_COUNTER(p) == 0) // ¿es un nodo fuente?
204  q.put(p); // sí ==> colocarlo en la cola
205  }
206 
207  RankList<List<typename GT::Node*>> ranks; // valor de retorno
208  while (not q.is_empty())
209  {
210  List<typename GT::Node*> rank;
212 
213  while (not q.is_empty()) // saca todos los nodos del nivel i
214  {
215  typename GT::Node * p = q.get(); // saque último fuente
216  rank.append(p); // insértelo en el rango topológico
217 
218  // decrementar grado entrada de cada nodo adyacente a p
219  for (Out_Iterator<GT, SA> it(p, sa); it.has_curr(); it.next())
220  {
221  typename GT::Node * tgt = it.get_tgt_node();
222  if (--NODE_COUNTER(tgt) == 0) // ¿tgt deviene fuente?
223  aq.put(tgt); // sí ==> colóquelo en cola auxiliar
224  }
225  }
226 
227  ranks.append(std::move(rank));
228  q.swap(aq);
229  }
230 
231  return ranks;
232  }
233 
234  void operator () (GT & g, DynDlist<DynList<typename GT::Node *>> & list)
235  {
236  this->ranks<>(g).swap(list);
237  }
238 
239  void operator () (GT & g, DynList<DynList<typename GT::Node *>> & list)
240  {
241  this->ranks<DynList>(g).swap(list);
242  }
243 
245  void operator () (GT & g, DynDlist<typename GT::Node*> & list)
246  {
247  this->perform<DynDlist>(g).swap(list);
248  }
249 };
250 
251 } // end namespace Aleph
252 
253 # endif // TOPOLOGICAL_SORT_H
void operator()(GT &g, DynDlist< typename GT::Node * > &list)
Definition: topological_sort.H:91
Definition: topological_sort.H:19
Definition: topological_sort.H:107
Definition: tpl_graph.H:751
#define IS_NODE_VISITED(p, bit)
Definition: aleph-graph.H:242
Definition: tpl_dynListQueue.H:22
List< typename GT::Node * > perform(GT &g)
Definition: topological_sort.H:129
#define NODE_COUNTER(p)
Definition: aleph-graph.H:226
Definition: tpl_graph.H:1186
void next()
Adelanta el iterador una posición.
Definition: filter_iterator.H:143
#define NODE_BITS(p)
Definition: aleph-graph.H:221
RankList< List< typename GT::Node * > > ranks(GT &g)
Definition: topological_sort.H:185
Definition: ahDry.H:13
T get()
Definition: tpl_dynListQueue.H:107
Definition: tpl_graph.H:694
Definition: List.H:23
List< typename GT::Node * > perform(GT &g)
Definition: topological_sort.H:66
T & put(const T &data)
Definition: tpl_dynListQueue.H:86

Leandro Rabindranath León