00001 //----------------------------------------------------------------------------- 00002 /** @file graph.h 00003 Graph class. 00004 00005 $Id: graph_8h-source.html,v 1.1.1.1 2003/08/07 19:41:39 emarkus Exp $ 00006 $Source: /usr/cvsroot/www_pathfind/libpathfind/0.1.0/doc/graph_8h-source.html,v $ 00007 */ 00008 //----------------------------------------------------------------------------- 00009 00010 #ifndef PATHFIND_GRAPH_H 00011 #define PATHFIND_GRAPH_H 00012 00013 #include <assert.h> 00014 #include <vector> 00015 00016 //----------------------------------------------------------------------------- 00017 00018 namespace PathFind 00019 { 00020 using namespace std; 00021 00022 /** %Graph with generic data attached to nodes and edges. */ 00023 template<class NODEINFO, class EDGEINFO> 00024 class Graph 00025 { 00026 public: 00027 /** %Edge in a graph with generic data attached. */ 00028 class Edge 00029 { 00030 public: 00031 Edge(); 00032 00033 Edge(int targetNodeId, const EDGEINFO& info) 00034 : m_targetNodeId(targetNodeId), 00035 m_info(info) 00036 { } 00037 00038 int getTargetNodeId() const 00039 { 00040 return m_targetNodeId; 00041 } 00042 00043 EDGEINFO& getInfo() 00044 { 00045 return m_info; 00046 } 00047 00048 const EDGEINFO& getInfo() const 00049 { 00050 return m_info; 00051 } 00052 00053 private: 00054 int m_targetNodeId; 00055 00056 EDGEINFO m_info; 00057 }; 00058 00059 /** %Node in a graph with generic data attached. */ 00060 class Node 00061 { 00062 public: 00063 Node() 00064 : m_nodeId(-1) 00065 { } 00066 00067 Node(int nodeId, const NODEINFO& info) 00068 : m_nodeId(nodeId), 00069 m_info(info) 00070 { } 00071 00072 void addOutEdge(const Edge& edge) 00073 { 00074 m_outEdges.push_back(edge); 00075 } 00076 00077 void removeOutEdge(int targetNodeId); 00078 00079 void clearOutEdges() 00080 { 00081 m_outEdges.clear(); 00082 } 00083 00084 NODEINFO& getInfo() 00085 { 00086 return m_info; 00087 } 00088 00089 const NODEINFO& getInfo() const 00090 { 00091 return m_info; 00092 } 00093 00094 const vector<Edge>& getOutEdges() const 00095 { 00096 return m_outEdges; 00097 } 00098 00099 private: 00100 int m_nodeId; 00101 00102 vector<Edge> m_outEdges; 00103 00104 NODEINFO m_info; 00105 }; 00106 00107 void addNode(int nodeId, const NODEINFO& info); 00108 00109 void addOutEdge(int sourceNodeId, int targetNodeId, 00110 const EDGEINFO& info); 00111 00112 void removeNodeEdges(int nodeId); 00113 00114 void removeLastNode() 00115 { 00116 m_nodes.erase(m_nodes.end()); 00117 } 00118 00119 void removeOutEdge(int sourceNodeId, int targetNodeId); 00120 00121 void clear() 00122 { 00123 m_nodes.clear(); 00124 } 00125 00126 const Node& getNode(int nodeId) const 00127 { 00128 assert(isValidNodeId(nodeId)); 00129 return m_nodes[nodeId]; 00130 } 00131 00132 NODEINFO& getNodeInfo(int nodeId) 00133 { 00134 return getNode(nodeId).getInfo(); 00135 } 00136 00137 const NODEINFO& getNodeInfo(int nodeId) const 00138 { 00139 return getNode(nodeId).getInfo(); 00140 } 00141 00142 const vector<Edge>& getOutEdges(int nodeId) const 00143 { 00144 assert(isValidNodeId(nodeId)); 00145 return m_nodes[nodeId].getOutEdges(); 00146 } 00147 00148 private: 00149 vector<Node> m_nodes; 00150 00151 Node& getNode(int nodeId) 00152 { 00153 assert(isValidNodeId(nodeId)); 00154 return m_nodes[nodeId]; 00155 } 00156 00157 bool isValidNodeId(int nodeId) const; 00158 }; 00159 } 00160 00161 //----------------------------------------------------------------------------- 00162 00163 namespace PathFind 00164 { 00165 using namespace std; 00166 00167 template<class NODEINFO, class EDGEINFO> 00168 void Graph<NODEINFO, EDGEINFO>::Node::removeOutEdge(int targetNodeId) 00169 { 00170 for (typename vector<Edge>::iterator i = m_outEdges.begin(); 00171 i != m_outEdges.end(); ++i) 00172 { 00173 if (i->getTargetNodeId() == targetNodeId) 00174 { 00175 m_outEdges.erase(i); 00176 break; 00177 } 00178 } 00179 } 00180 00181 template<class NODEINFO, class EDGEINFO> 00182 void Graph<NODEINFO, EDGEINFO>::addNode(int nodeId, const NODEINFO& info) 00183 { 00184 assert(nodeId >= 0); 00185 unsigned int size = static_cast<unsigned int>(nodeId + 1); 00186 if (m_nodes.size() < size) 00187 m_nodes.resize(size); 00188 m_nodes[nodeId] = Node(nodeId, info); 00189 } 00190 00191 template<class NODEINFO, class EDGEINFO> 00192 void Graph<NODEINFO, EDGEINFO>::removeNodeEdges(int nodeId) 00193 { 00194 const vector<Edge>& edges = m_nodes[nodeId].getOutEdges(); 00195 for (typename vector<Edge>::const_iterator i = edges.begin(); 00196 i != edges.end(); ++i) 00197 { 00198 m_nodes[i->getTargetNodeId()].removeOutEdge(nodeId); 00199 } 00200 m_nodes[nodeId].clearOutEdges(); 00201 } 00202 00203 template<class NODEINFO, class EDGEINFO> 00204 void Graph<NODEINFO, EDGEINFO>::addOutEdge(int sourceNodeId, 00205 int targetNodeId, 00206 const EDGEINFO& info) 00207 { 00208 assert(isValidNodeId(sourceNodeId)); 00209 assert(isValidNodeId(targetNodeId)); 00210 m_nodes[sourceNodeId].addOutEdge(Edge(targetNodeId, info)); 00211 } 00212 00213 template<class NODEINFO, class EDGEINFO> 00214 bool Graph<NODEINFO, EDGEINFO>::isValidNodeId(int nodeId) const 00215 { 00216 return nodeId >= 0 00217 && static_cast<unsigned int>(nodeId) < m_nodes.size(); 00218 } 00219 } 00220 00221 //----------------------------------------------------------------------------- 00222 00223 #endif