@@ -19,6 +19,10 @@ typedef struct {
1919 std::vector<AdjacencyListGraphNode *> nodes;
2020 std::unordered_map<std::string, GraphEdge*> edges;
2121 std::unordered_map<std::string, AdjacencyListGraphNode*> node_map;
22+ std::unordered_map<int , AdjacencyListGraphNode*> id_map;
23+ std::unordered_map<int , std::string> id_to_name;
24+ std::unordered_map<std::string, int > name_to_id;
25+ int next_id;
2226
2327} AdjacencyListGraph;
2428
@@ -34,6 +38,9 @@ static void AdjacencyListGraph_dealloc(AdjacencyListGraph* self) {
3438 self->edges .clear ();
3539
3640 self->node_map .clear ();
41+ self->id_map .clear ();
42+ self->id_to_name .clear ();
43+ self->name_to_id .clear ();
3744
3845 Py_TYPE (self)->tp_free (reinterpret_cast <PyObject*>(self));
3946}
@@ -46,38 +53,38 @@ static PyObject* AdjacencyListGraph_new(PyTypeObject* type, PyObject* args, PyOb
4653 new (&self->nodes ) std::vector<AdjacencyListGraphNode*>();
4754 new (&self->edges ) std::unordered_map<std::string, GraphEdge*>();
4855 new (&self->node_map ) std::unordered_map<std::string, AdjacencyListGraphNode*>();
56+ new (&self->id_map ) std::unordered_map<int , AdjacencyListGraphNode*>();
57+ new (&self->id_to_name ) std::unordered_map<int , std::string>();
58+ new (&self->name_to_id ) std::unordered_map<std::string, int >();
59+
60+ self->next_id = 0 ;
4961
5062 Py_ssize_t num_args = PyTuple_Size (args);
5163 for (Py_ssize_t i = 0 ; i < num_args; ++i) {
5264 PyObject* node_obj = PyTuple_GetItem (args, i);
5365 if (!PyObject_IsInstance (node_obj, (PyObject*)&AdjacencyListGraphNodeType)) {
5466 PyErr_SetString (PyExc_TypeError, " All arguments must be AdjacencyListGraphNode instances" );
55-
56- self->nodes .~vector ();
57- self->edges .~unordered_map ();
58- self->node_map .~unordered_map ();
59- Py_TYPE (self)->tp_free (reinterpret_cast <PyObject*>(self));
6067 return NULL ;
6168 }
6269
6370 AdjacencyListGraphNode* node = reinterpret_cast <AdjacencyListGraphNode*>(node_obj);
6471
6572 if (self->node_map .find (node->name ) != self->node_map .end ()) {
6673 PyErr_Format (PyExc_ValueError, " Duplicate node with name '%s'" , node->name .c_str ());
67-
68- self->nodes .~vector ();
69- self->edges .~unordered_map ();
70- self->node_map .~unordered_map ();
71- Py_TYPE (self)->tp_free (reinterpret_cast <PyObject*>(self));
7274 return NULL ;
7375 }
7476
77+ node->internal_id = self->next_id ++;
78+
7579 Py_INCREF (node);
7680 self->nodes .push_back (node);
7781 self->node_map [node->name ] = node;
82+ self->id_map [node->internal_id ] = node;
83+ self->id_to_name [node->internal_id ] = node->name ;
84+ self->name_to_id [node->name ] = node->internal_id ;
7885 }
79- PyObject* impl_str = PyUnicode_FromString (" adjacency_list" );
8086
87+ PyObject* impl_str = PyUnicode_FromString (" adjacency_list" );
8188 if (PyObject_SetAttrString (reinterpret_cast <PyObject*>(self), " _impl" , impl_str) < 0 ) {
8289 Py_DECREF (impl_str);
8390 PyErr_SetString (PyExc_RuntimeError, " Failed to set _impl attribute" );
@@ -112,9 +119,14 @@ static PyObject* AdjacencyListGraph_add_vertex(AdjacencyListGraph* self, PyObjec
112119 return NULL ;
113120 }
114121
122+ node->internal_id = self->next_id ++;
123+
115124 Py_INCREF (node);
116125 self->nodes .push_back (node);
117126 self->node_map [node->name ] = node;
127+ self->id_map [node->internal_id ] = node;
128+ self->id_to_name [node->internal_id ] = node->name ;
129+ self->name_to_id [node->name ] = node->internal_id ;
118130
119131 Py_RETURN_NONE;
120132}
@@ -126,17 +138,15 @@ static PyObject* AdjacencyListGraph_is_adjacent(AdjacencyListGraph* self, PyObje
126138 if (!PyArg_ParseTuple (args, " ss" , &node1_name_c, &node2_name_c))
127139 return NULL ;
128140
129- std::string node1_name (node1_name_c);
130- std::string node2_name (node2_name_c);
131-
132- auto it1 = self->node_map .find (node1_name);
133- if (it1 == self->node_map .end ()) {
141+ auto it1 = self->name_to_id .find (node1_name_c);
142+ if (it1 == self->name_to_id .end ()) {
134143 PyErr_SetString (PyExc_KeyError, " node1 not found" );
135144 return NULL ;
136145 }
137- AdjacencyListGraphNode* node1 = it1->second ;
146+ int id1 = it1->second ;
147+ AdjacencyListGraphNode* node1 = self->id_map [id1];
138148
139- if (node1->adjacent .find (node2_name ) != node1->adjacent .end ()) {
149+ if (node1->adjacent .find (node2_name_c ) != node1->adjacent .end ()) {
140150 Py_RETURN_TRUE;
141151 } else {
142152 Py_RETURN_FALSE;
@@ -156,13 +166,13 @@ static PyObject* AdjacencyListGraph_neighbors(AdjacencyListGraph* self, PyObject
156166 if (!PyArg_ParseTuple (args, " s" , &node_name_c))
157167 return NULL ;
158168
159- std::string node_name (node_name_c);
160- auto it = self->node_map .find (node_name);
161- if (it == self->node_map .end ()) {
169+ auto it = self->name_to_id .find (node_name_c);
170+ if (it == self->name_to_id .end ()) {
162171 PyErr_SetString (PyExc_KeyError, " Node not found" );
163172 return NULL ;
164173 }
165- AdjacencyListGraphNode* node = it->second ;
174+ int id = it->second ;
175+ AdjacencyListGraphNode* node = self->id_map [id];
166176
167177 PyObject* neighbors_list = PyList_New (0 );
168178 if (!neighbors_list) return NULL ;
@@ -180,23 +190,27 @@ static PyObject* AdjacencyListGraph_remove_vertex(AdjacencyListGraph* self, PyOb
180190 if (!PyArg_ParseTuple (args, " s" , &name_c))
181191 return NULL ;
182192
183- std::string name (name_c);
184- auto it = self->node_map .find (name);
185- if (it == self->node_map .end ()) {
193+ auto it = self->name_to_id .find (name_c);
194+ if (it == self->name_to_id .end ()) {
186195 PyErr_SetString (PyExc_KeyError, " Node not found" );
187196 return NULL ;
188197 }
189198
190- AdjacencyListGraphNode* node_to_remove = it->second ;
199+ int id = it->second ;
200+ AdjacencyListGraphNode* node_to_remove = self->id_map [id];
201+ std::string name = node_to_remove->name ;
191202
192203 auto & nodes_vec = self->nodes ;
193204 nodes_vec.erase (std::remove (nodes_vec.begin (), nodes_vec.end (), node_to_remove), nodes_vec.end ());
194205
195- self->node_map .erase (it);
206+ self->node_map .erase (name);
207+ self->id_map .erase (id);
208+ self->name_to_id .erase (name);
209+ self->id_to_name .erase (id);
196210
197211 Py_XDECREF (node_to_remove);
198212
199- for (auto & node_pair : self->node_map ) {
213+ for (auto & node_pair : self->id_map ) {
200214 AdjacencyListGraphNode* node = node_pair.second ;
201215 auto adj_it = node->adjacent .find (name);
202216 if (adj_it != node->adjacent .end ()) {
@@ -207,17 +221,11 @@ static PyObject* AdjacencyListGraph_remove_vertex(AdjacencyListGraph* self, PyOb
207221
208222 for (auto it = self->edges .begin (); it != self->edges .end (); ) {
209223 const std::string& key = it->first ;
210-
211- bool involves_node = false ;
212224 size_t underscore = key.find (' _' );
213- if (underscore != std::string::npos) {
214- std::string source = key.substr (0 , underscore);
215- std::string target = key.substr (underscore + 1 );
216- if (source == name || target == name)
217- involves_node = true ;
218- }
225+ std::string src = key.substr (0 , underscore);
226+ std::string dst = key.substr (underscore + 1 );
219227
220- if (involves_node ) {
228+ if (src == name || dst == name ) {
221229 Py_XDECREF (it->second );
222230 it = self->edges .erase (it);
223231 } else {
0 commit comments