Página principal | Lista de namespace | Jerarquía de la clase | Lista de componentes | Directories | Lista de archivos | Miembros del Namespace  | Miembros de las clases | Archivos de los miembros | Páginas relacionadas

ADH_Graph.cpp

Ir a la documentación de este archivo.
00001 /* ADH_Graph.cpp (C) 2007  [email protected]  */
00002 
00003 #include "ADH_Graph.h"
00004 
00005 /** \file  ADH_Graph.cpp
00006     \brief Archivo de implementaci¢n para \c ADH_Graph.h
00007 
00008     \author Adolfo Di Mare <[email protected]>
00009     \date   2007
00010 */
00011 
00012 
00013 namespace ADH {
00014 
00015 /** Verifica la invariante del grafo.
00016     - Regresa \c "true" si el grafo \c "DDD" contiene un valor correcto
00017     - Podría retornar \c "true" para un grafo lista cuyo valor está corrupto
00018     - Podría no retornar si el grafo tiene su valor corrupto
00019 
00020     - Como los valores del grafo están ordenados, verifica
00021       que la lista que DDD contiene esté ordenada
00022 
00023     \par Rep Diagrama de la clase
00024     \code
00025         m_DICC[]
00026     +------+-----------------------------------+
00027     |      | +---------+---------+-----------+ |
00028     |  F   | | A(1)=>2 | A(2)=>8 | A(3)==>64 | |
00029     |      | +---------+---------+-----------+ |
00030     +------+-----------------------------------+
00031     |      | +------+                          |         A(1)         C(1)
00032     | A(1) | | B=>2 |                          |        /    \       /    \
00033     |      | +------+                          |       /      \     /      \
00034     +------+-----------------------------------+    F----A(2)----B--        --D
00035     |      | +------+                          |       \      /     \      /
00036     | A(2) | | B=>8 |                          |        \    /       \    /
00037     |      | +------+                          |         A(3)         C(2)
00038     +------+-----------------------------------+
00039     |      | +-------+                         |
00040     | A(3) | | B=>64 |                         |    G.set("F", "A(1)",  2 ); G.set( "A(1)", "B",  2 );
00041     |      | +-------+                         |    G.set("F", "A(2)",  8 ); G.set( "A(2)", "B",  8 );
00042     +------+-----------------------------------+    G.set("F", "A(3)", 64 ); G.set( "A(3)", "B", 64 );
00043     |      | +---------+----------+            |
00044     |  B   | | C(1)=>3 | C(2)=>27 |            |    G.set("B", "C(1)",  3 ); G.set( "C(1)", "D",  3 );
00045     |      | +---------+----------+            |    G.set("B", "C(2)", 27 ); G.set( "C(2)", "D", 27 );
00046     +------+-----------------------------------+
00047     |      | +------+                          |
00048     | C(1) | | D=>2 |                          |
00049     |      | +------+                          |
00050     +------+-----------------------------------+
00051     |      | +------+                          |
00052     | C(2) | | D=>8 |                          |
00053     |      | +------+                          |
00054     +------+-----------------------------------+
00055     |      | +-+                               |
00056     |  D   | | |                               |     D no es salida de ninguna arista
00057     |      | +-+                               |     - Su diccionario está vacío
00058     +------+-----------------------------------+
00059     \endcode
00060 
00061     - El grafo está implementado como un diccionario que contiene otro diccionario.
00062     - La llave del diccionario principal es el vértice que comienza un arco.
00063     - Cada vértice tiene asociado un diccionario cuya llave es el vértice de destino.
00064       Este es el diccionario que representa cada arista.
00065     - El valor numérico asociado en el diccionario de cada arista es el valor de la arista.
00066     - Si un vértice no participa en ninguna arista, tampoco aparece en el grafo.
00067 /// - En el grado sólo están almacenados los vértices que participan en alguna arista.
00068 */
00069 bool check_ok( const Graph & DDD ) {
00070     if ( & DDD == 0 ) {
00071         /// - Invariante: ningún objeto puede estar almacenado en la posición nula.
00072         return false;
00073     }
00074     return true;
00075 }
00076 
00077 /// Establece que el grafo tiene la arista \c src->dst con valor \c "val".
00078 /// - Si ya la arista estaba en el grafo, no la agrega ni le cambia el valor asociado.
00079 void Graph::set( const std::string & src , const std::string & dst , int val ) {
00080     {   // Agrega primero los 2 vértices del arco (si no han sido agregados antes)
00081         m_DICC.insert( make_pair( src, Rep::mapped_type() ) );
00082         m_DICC.insert( make_pair( dst, Rep::mapped_type() ) ); // lo agrega si no estaba
00083     }
00084     {   Rep::iterator it = m_DICC.find( src );
00085         // Ya existe ese vértice en el diccionario
00086         it->second.insert( make_pair( dst , val ) );
00087     }
00088     return;
00089 
00090 /*  Nota:
00091     No es posible implementar esta operación usando 2 iteradores para recorrer
00092     "m_DICC". Si uno lo hace, el programa explota en tiempo de ejecución.
00093     - Los iteradores del diccionario std::map<> no se pueden copiar, pues no
00094       tienen su "operator=()" definido.
00095     - Un diccionario sólo puede tener un iterador que no sea "const", que es el
00096       único que puede cambiarlo. Los otros iteradores deben ser "const".
00097     - Así se evita que, al usar más de 1 iterador, el diccionario quede modificado
00098       de una forma indeseable.
00099     - Como no existe std::map<>::iterator.operator=(), lo más saludable al usar
00100       un iterador para modificar std::map<> es incluir en bloques { } el código
00101       en donde está definido el iterador, porque la única forma de inicializar
00102       std::map<>::iterator es usando su constructor:
00103       { Rep::iterator it = m_DICC.find( src ); ...  }
00104 */
00105 }
00106 
00107 /// Establece que el grafo tiene el vértice \c vtx.
00108 void Graph::set( const std::string & vtx ) {
00109 #if 1
00110         {   // Agrega el vértice sin arco (diccionario asociado vacío)
00111         m_DICC.insert( make_pair( vtx, Rep::mapped_type() ) );
00112         }
00113 #else
00114         Rep::iterator it = m_DICC.find( vtx );
00115     if ( it == m_DICC.end() ) {
00116         // Agrega el vértice sin aristas.
00117         Rep::mapped_type D;
00118         m_DICC.insert( make_pair( vtx , D ) );
00119     }
00120 #endif
00121 }
00122 
00123 /** Retorna \c "true" si existe el vértice \c vtx.
00124 
00125     \dontinclude test_Graph.cpp
00126     \skipline    test::isVertex()
00127     \until       }}
00128     \see         test_Graph::test_isVertex()
00129 */
00130 bool Graph::isVertex( const std::string & vtx ) const {
00131     Graph::Rep::const_iterator it = m_DICC.find( vtx );
00132     return ( it != m_DICC.end() );
00133 }
00134 
00135 /** Retorna \c "true" si existe el arco \c src->dst.
00136     - Si el arco existe, en \c val se copia el valor asociado al arco.
00137     - Si el arco no existe, retorna \c "false" y no cambia el valor de \c val.
00138 
00139     \dontinclude test_Graph.cpp
00140     \skipline    test::isVertex()
00141     \until       }}
00142     \see         test_Graph::test_isVertex()
00143 */
00144 bool Graph::isArc( const std::string & src , const std::string & dst , int & val ) const {
00145     Graph::Rep::const_iterator it = m_DICC.find( src );
00146     if ( it == m_DICC.end() ) {
00147         return false;
00148     }
00149     else {
00150         // Ya existe ese vértice en el diccionario
00151         Graph::mapped_type::const_iterator jt = it->second.find( dst );
00152         if ( jt == it->second.end() ) {
00153             return false;
00154         }
00155         else {
00156             val = jt->second;
00157             return true;
00158         }
00159     }
00160 }
00161 
00162 /// Graba el valor de \c "G" en el flujo \c "COUT".
00163 std::ostream& operator<< (std::ostream &COUT, const Graph& G) {
00164     Graph::Rep::const_iterator it = G.m_DICC.begin();  // recorre m_DICC[]
00165     for ( ; it != G.m_DICC.end(); ++it ) {
00166         COUT << it->first << " ==> [";
00167         Graph::mapped_type::const_iterator jt = it->second.begin();
00168         while ( jt != it->second.end() ) {
00169             COUT << '<' << jt->second << '>' << jt->first ;
00170             ++jt;
00171             if ( jt != it->second.end() ) {
00172                 COUT << " , ";
00173             }
00174         }
00175         COUT << ']' << std::endl;
00176     }
00177     return COUT;
00178 }  // operator <<
00179 
00180 /// Graba el valor de \c "G" en el flujo \c "COUT".
00181 void dump( std::ostream & COUT, const Graph& G ) {
00182     Graph::Rep::const_iterator it = G.m_DICC.begin();
00183     for ( ; it != G.m_DICC.end(); ++it ) {
00184         Graph::Rep::const_iterator jt = G.m_DICC.begin();
00185         for ( ; jt != G.m_DICC.end(); ++jt ) {
00186             int val = 666;
00187             if ( G.isArc( it->first , jt->first , val ) ) {
00188                 COUT << it->first << "->" << jt->first << " == " << val << std::endl;
00189             }
00190         }
00191     }
00192 }
00193 
00194 /** Determina si existe un camino en el grafo comenzando en \c "src" y terminando en \c "dst".
00195     - Retorna \c "true" cuando el camino existe, y \c "false" en caso contrario.
00196     - La lista \c "C" contiene la secuencia de nodos del camino.
00197     - Si no hay camino, la lista \c "C" queda vacía.
00198 
00199     \dontinclude test_Graph.cpp
00200     \skipline    test::diagram()
00201     \until       }}
00202     \skipline    test::connected()
00203     \until       }}
00204     \see         test_Graph::test_connected()
00205 */
00206 bool Graph::connected( const std::string & src , const std::string & dst , std::list< std::string > & C ) {
00207     int val = 0;
00208         bool res = false;
00209         Graph::Rep::const_iterator it = m_DICC.find( src );
00210         
00211     if ( it == m_DICC.end() ) {
00212         return false;
00213     }
00214     else {
00215 
00216                 C.push_back(src);
00217                 for (int i = 0; i != it->second.size(); ++i ) {
00218                         std::map<  std::string, int >::const_iterator jt = it->second.begin();
00219                         for ( ; jt != it->second.end(); ++jt ) {
00220                                 if ( isArc(jt->first, dst, val)){
00221                                         C.push_back(jt->first);
00222                                         C.push_back(dst);
00223                                         res = true;
00224                                         return res;
00225                                 }
00226                                 else{
00227                                         res = connected(jt->first, dst, C);                             
00228                                 }
00229 
00230                         }
00231                 
00232                         //++it
00233                 }
00234 
00235         }
00236 
00237         return res;
00238 }
00239 
00240 
00241 } // namespace ADH
00242 
00243 // EOF: ADH_Graph.cpp

Generado el Thu Nov 15 15:47:43 2007 para Clase ADH_Graph: por  doxygen 1.4.1
Hosted by www.Geocities.ws

1