After a thousand of attempts to Google/bypass that using pointers, I decided myself to post this question to you guys.
Here's the problem: I'm trying to create a minimum spanning tree from a graph that I previously made. I'm using Kruscal's Algorithm for that, which is about checking every arc from the shorter to the longest and taking vertexes that I miss.
To do that, I implemented my graph using a stl::map as an adjaciences matrix. The map is made of the following pair: (double distance, pair-Vertex*, Vertex*- ).
The algorithm requires you to distinguish between a pair you haven't entirely, and one of which you need only one vertex: the former needs you to create another set and you have to gradually connect all of those sets by getting the arcs that connect them (those arcs being of course those having 1 vertex in a set and 1 vertex in another one).
I decided to implement Kruscal this way: my MST (min spanning tree) is a stl::map itself, and so every subset is. They are organized in a list of maps (which I typedef'd map_t): every time I get a node of which I miss 2 vertexes, one tree is added to the list and that node is put into it. The connections will make my MST come into the first node of the list.
Code seems ok to me, but there's no way that list iterators are happy with that. Here's the code:
map_t Grafo::createKruscalMST() {
mapIterator_t iterator = adjmatrix.begin();
mapIterator_t end = adjmatrix.end()--;
list<map_t> MST;
list<map_t>::iterator listend = MST.end(); // Per puntare alla fine della lista devo fare end()-1 perché end() è il primo dopo la fine
//MST.resize(1);
bool zeromatch = true;
list<map_t>::iterator memo1 = MST.end(); // Valore che non c'è: MST.end() punta al primo elemento dopo la fine della lista
int common;
list<map_t>::iterator j = MST.begin();
MST.resize(1);
//++j;
*j = setUnion(*j, iterator); // Inserisco in automatico il primo nodo
while (iterator != adjmatrix.end() )
{
++iterator;
zeromatch = true;
memo1 = MST.end();
for (j = MST.begin(); j != MST.end(); ++j)
{
common = howManyInCommon(*j, iterator);
if (common == 2) zeromatch = false;
if (common == 1)
{
zeromatch = false;
if (memo1 == MST.end() ) memo1 = j; // Se nessun altro prima di me aveva 1 e un solo match, mi ricordo della posizione
else
{
*memo1 = treeMerge(*memo1, *j); // Se c'era un altro prima di me, lo copio tutto nel precedente e poi cancello l'altra occorrenza.
MST.erase(j); // Questo farà affiorare l'MST nel nodo di testa, alla lunga.
*memo1 = setUnion(*memo1, iterator); // Includo anche il collegamento tra i due semialberi.
memo1 = MST.end(); // Fatto ciò, provvedo a resettare l'iteratore di appoggio
}
}
}
if (memo1 != MST.end() )
*memo1 = setUnion(*memo1, iterator);
if (zeromatch == true )
{
//MST.resize(MST.size()+1);
//listend = MST.end()--;
MST.push_back( setUnion(MST.back(), iterator) );
}
}
return MST.front();
}
int howManyInCommon(map_t disjset, mapIterator_t vertexptr) {
int j = 0; // Parto da 0 e conto direttamente quanti ne ho in comune (molto meglio di una concatenazione di if)
if (vertexptr->second.first->getRepresenter() == disjset.begin()->second.first->getRepresenter() )
j++;
if (vertexptr->second.second->getRepresenter() == disjset.begin()->second.first->getRepresenter() )
j++;
return j;
}
map_t setUnion(map_t Tree, mapIterator_t i) {
if (Tree.empty() ) {
Tree.insert(*i);
Tree.begin()->second.second->setRepresenter(Tree.begin()->second.first->getRepresenter() ); // Il rappresentante del secondo nodo diventa uguale a quello del primo
}
else {
i->second.first->setRepresenter(Tree.begin()->second.first->getRepresenter() );
i->second.second->setRepresenter(Tree.begin()->second.first->getRepresenter() );
// Nodo della mappa - Nodo con pair <double, pair<Nodo*,Nodo*> - Devo lavorare sul secondo del pair esterno, dunque.
Tree.insert(*i);
}
return Tree;
}
map_t treeMerge(map_t Dest, map_t Source) {
mapIterator_t srciterator = Source.begin();
while (srciterator != Source.end() ) {
Dest = setUnion(Dest, srciterator);
++srciterator;
}
return Dest;
}