Doubt with reported errors with Valgrind

0

I am learning to use Valgrind to detect errors in my program. I have encountered a memory leak error. This is the code:

Class node

#ifndef NODO_H_INCLUDED
#define NODO_H_INCLUDED

#include <iostream>

template <typename DATOA, typename DATON>
struct arista;//declaración previa

template <typename DATON, typename DATOA>
struct nodo
{
    DATON datonodo;
    unsigned short int nPadres;
    nodo<DATON,DATOA>* siguiente;
    arista<DATOA,DATON>* adyacente;
    //constructor
    nodo (DATON N=0, unsigned short int numPadres=0, nodo<DATON,DATOA>* s=nullptr, arista<DATOA, DATON>* a=nullptr):datonodo(N),nPadres(numPadres),siguiente(s),adyacente(a) {}
    //constructor copia
    nodo (const nodo<DATON,DATOA>& n)
    {
        std::cout<<"nodo Constructor copia"<<std::endl;
        datonodo=n.datonodo;
        nPadres=n.nPadres;
        siguiente=nullptr;
        adyacente=nullptr;            
    }
    //destructor
    ~nodo()
    {
        siguiente=nullptr;
        adyacente=nullptr;
        //borrar pila?
        //borrar datonodo?            
    }
    //operador de asignacion
    nodo& operator = (const nodo<DATON, DATOA>& n)
    {
        if (this!=&n)
        {
            datonodo=n.datonodo;
            nPadres=n.nPadres;
            siguiente=nullptr;
            adyacente=nullptr;
        }
        return *this;
    }
};

#endif // NODO_H_INCLUDED

Class edge

#ifndef ARISTA_H_INCLUDED
#define ARISTA_H_INCLUDED

template <typename, typename>
struct nodo;

template <typename DATOA, typename DATON>
struct arista
{
    DATOA datoarista;
    nodo<DATON,DATOA>* destino;
    nodo<DATON,DATOA>* origen;
    arista<DATOA,DATON>* siguiente;
    arista<DATOA,DATON>* anterior;
    //constructores
    arista(DATOA A=0, nodo<DATON,DATOA>* d=nullptr, nodo<DATON,DATOA>* o=nullptr,
           arista<DATOA,DATON>* s=nullptr, arista<DATOA,DATON>* an=nullptr):datoarista(A),destino(d),origen(o),
           siguiente(s), anterior(an) {}

    arista (const arista<DATOA,DATON>& a)
    {
        datoarista=a.datoarista;
        destino=nullptr;
        origen=nullptr;
        siguiente=nullptr;
        anterior=nullptr;
    }
    //operador de asignacion
    arista& operator = (const arista<DATOA, DATON>& a)
    {
        if (this!=&a)
            {
                datoarista=a.datoarista;
                destino=nullptr;
                origen=nullptr;
                siguiente=nullptr;
                anterior=nullptr;
            }
        return *this;
    }

    ~arista()
    {
        //std::cout<<"Destructor arista"<<std::endl;
    }
};

#endif // ARISTA_H_INCLUDED

Class graph

#ifndef GRAFO_H
#define GRAFO_H

#include <iostream>
#include <stack>
#include <list>

#include "arista.h"
#include "nodo.h"

template <typename DATON, typename DATOA>
class Grafo
{
    typedef DATON datonodo_t;
    typedef DATOA datoarista_t;
    typedef nodo<datonodo_t,datoarista_t>* pNodo;
    typedef arista<datoarista_t,datonodo_t>* pArista;
    typedef nodo<datonodo_t,datoarista_t> t_nodo;
    typedef arista<datoarista_t,datonodo_t> t_arista;


public:
    //constructor
    Grafo():Raiz(nullptr),nNodos(0)
    {
        std::cout<<"Constructor grafo"<<std::endl;
    }
    Grafo (pNodo nodo)
    {
        //Raiz = new t_nodo(*nodo);
        Raiz = nodo;
        nNodos=1;
    }
    Grafo (datonodo_t nodo)
    {
        Raiz = new t_nodo(nodo);
    }
    //constructor copia
    Grafo (const Grafo& G);
    //funciones
    /************auxiliares de nodos y aristas***************/
    void anadirNodo (pNodo& n);
    void eliminarNodo(pNodo& n);
    //void anadirArista (pNodo& NodoOrigen, pNodo& NodoDestino, pArista& precedente, pArista& NuevaArista);
    void eliminarArista (pArista& A);
    pArista hallarArista (pNodo& nodopadre, pNodo& nodohijo);
    /*********insertar,eliminar,copiar elementos del grafo*******************/
    void Insertar (pNodo& padre, pNodo& hijo, pArista& NuevaArista, int posicion=-1);
    void borrarNodos(pArista& A);
    void Copiar(pNodo& padre, pNodo& hijo, pArista NuevaArista, pArista precedente=nullptr);
    pNodo CrearGrafoAPartirDeNodo(const pNodo& nodo);
    /******funciones para recorrer el grafo*************************/
    std::list<pNodo> recorrerNodos() const;
    std::list<pNodo>& recorrerGrafo(const pNodo& inicio);
    std::list<pNodo>& lista_recorrerGrafo(const pNodo& inicio);
    /**********comprobaciones necesarias****************/
    bool esReferenciaCircular(pNodo& padre, pNodo& hijo);
    bool existeHermano (pNodo& padre, pNodo& hijo);
    bool existeNodo (const pNodo& n);
    /***********otras*******************************/
    void guardaAristas (const pNodo& n);
    void guardaAristasParaCopia (const pNodo& n);
    pNodo posicionarseEnNodo(const datonodo_t& dato);
    template <typename T>
    void VaciarPila(std::stack<T>& pila);
    /***********consultoras*************************/
    const pNodo& LeeRaiz() const
    {
        return Raiz;
    }
    ~Grafo();

private:

    pNodo Raiz;
    int nNodos;
    std::stack<pArista> pilaAristas;
    std::stack<pArista> pilaAristasParaCopia;
    std::stack<pNodo> pilaNodos;
    std::list<pNodo>nodos;
    std::stack<std::pair<pArista,int> >aristasConNiveles;
    std::list<std::pair<pNodo,int> >nodosConNiveles;
    //funciones privadas porque son de uso interno
    void InsertarHijo(pNodo& padre, pNodo& hijo, pArista& NuevaArista, pArista& precedente=nullptr);
    void InsertarHijo(pNodo& padre, pNodo& hijo, datoarista_t valorArista, pArista precedente=nullptr);
};

//********************//
//destructor del grafo//
//********************//
template <typename datonodo_t, typename datoarista_t>
Grafo<datonodo_t,datoarista_t>::~Grafo()
{
    std::cout<<"Iniciamos el destructor"<<std::endl;
    //borro la pila de aristas antes de usarla.
    VaciarPila(pilaAristas);
    pArista A;
    //meto todas las arista del nodo Raiz en la pila
    guardaAristas(Raiz);
    //empiezo a borrar todas las ramas que hay en la pila
    while (!pilaAristas.empty())
    {
        A=pilaAristas.top();
        pilaAristas.pop();
        borrarNodos(A);
    }
    delete Raiz;
    std::cout<<"Borrada la raiz"<<std::endl;
}

//*****************//
//constructor copia//
//*****************//
template <typename datonodo_t, typename datoarista_t>
Grafo<datonodo_t, datoarista_t>::Grafo (const Grafo<datonodo_t, datoarista_t>& G)
{
    std::cout<<"CONSTRUCTOR COPIA"<<std::endl;
    Raiz = CrearGrafoAPartirDeNodo(G.Raiz);
    std::cout<<"Copia terminada"<<std::endl;
}

//**************//
//añadir un nodo//
//**************//
template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::anadirNodo(pNodo& n)
{
    if (Raiz==nullptr)
    {
        Raiz=n;
    }
    else
    {
        pNodo indice=Raiz;
        //me posiciono al final de la lista
        while (indice && indice->siguiente!=0)
        {
            indice=indice->siguiente;
        }
        indice->siguiente=n;
    }
    nNodos++;
}

//****************//
//eliminar un nodo//
//****************//
template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::eliminarNodo(pNodo& n)
{
    pNodo anterior=Raiz;
    //avanzo anterior hasta el nodo anterior al que quiero borrar
    while (anterior->siguiente!=n)
    {
        anterior=anterior->siguiente;
    }
    if (anterior==Raiz)//primer elemento
    {
        Raiz->siguiente=n->siguiente;
    }
    else
    {
        anterior->siguiente=n->siguiente;
    }
    delete n;
    nNodos--;
}

//*******************//
//eliminar una arista//
//*******************//
template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::eliminarArista(pArista& A)
{
    pArista aux = A;
    pNodo indice=Raiz;
    //veo si la arista a borrar es la adyacente de algún nodo (primera arista)
    while (indice && indice->adyacente!=A)
    {
        indice=indice->siguiente;
    }
    if (indice)//si finalmente la arista a borrar es adyacente de indice
    {
        //si es arista única
        if (!A->anterior && !A->siguiente)
        {
            //std::cout<<"Es arista unica!!!"<<std::endl;
        }
        indice->adyacente = aux->siguiente;
    }
    if (aux->anterior)
    {
        aux->anterior->siguiente = aux->siguiente;
    }
    if (aux->siguiente)
    {
        aux->siguiente->anterior=aux->anterior;
    }
    delete aux;
}

//***********************************************//
//borrar todos los nodos que penden de una arista//
//***********************************************//

template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::borrarNodos(pArista& A)
{
    pNodo hijo=A->destino;
    //quitar un padre al nodo hijo
    if (hijo->nPadres>0) hijo->nPadres--;
    //si todavía es hijo de algún padre....
    if (hijo->nPadres)
    {
        //...me limito a borrar la arista que une al padre con el hijo
        eliminarArista(A);
    }
    else //si se queda huerfanito
    {
        //si el hijo es hoja no tiene aristas que salgan de él, luego adyacente apunta a 0
        if (!hijo->adyacente)
        {
            //me posiciono en la arista a borrar
            eliminarArista(A);
            eliminarNodo(hijo);//lo saco de la lista general de nodos
        }
        else
        {
            guardaAristas(hijo);
            eliminarArista(A);
            eliminarNodo(hijo);
            while (!pilaAristas.empty())
            {
                A=pilaAristas.top();
                pilaAristas.pop();
                borrarNodos(A);
            }
        }
    }
}

/***********************/
/****Insertar nodo *****/
/***********************/

template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::Insertar(pNodo& padre, pNodo& hijo, pArista& NuevaArista, int posicion)
{
    if (Raiz==nullptr)
    {
        Raiz = padre;
    }
    if (!existeNodo(padre))
    {
        anadirNodo(padre);
    }
    if (!existeNodo(hijo))
    {
        anadirNodo(hijo);
    }
    //inserto la arista
    if (!esReferenciaCircular(padre,hijo) && !existeHermano(padre,hijo))//comprobacion necesaria
    {
        hijo->nPadres++;//añado un padre
        NuevaArista->origen=padre;
        NuevaArista->destino=hijo;
        //caso 1. Primer nodo que cuelga del nodo padre
        if (!padre->adyacente)
        {
            padre->adyacente = NuevaArista;
        }
        else
        {
            //caso 2. Poner el nuevo nodo en primer lugar habiendo otros nodos existentes
            if (posicion==0)
            {
                NuevaArista->siguiente=padre->adyacente;
                padre->adyacente->anterior=NuevaArista;
                padre->adyacente=NuevaArista;
            }
            else//casos 3 y 4. El primer paso comun es situar la arista precedente a la que quiero insertar
            {
                pArista precedente = padre->adyacente;
                //caso 3. Si no se especifica posicion esta vale -1 y se inserta al final
                if (posicion<0)
                {
                    while(precedente && precedente->siguiente)
                    {
                        //std::cout<<"INSERTO AL FINALe"<<std::endl;
                        precedente=precedente->siguiente;
                    }
                }
                //caso 4. Me situo en la posicion dada
                else
                {
                    //std::cout<<"INSERTO POR POSICION"<<std::endl;
                    for (int i=0; i<posicion-1; i++)
                    {
                        precedente = precedente->siguiente;
                    }
                }
                //por ultimo ligo la nueva arista
                if (precedente && precedente->siguiente)
                {
                    precedente->siguiente->anterior=NuevaArista;
                }
                NuevaArista->siguiente=precedente->siguiente;
                NuevaArista->anterior=precedente;
                precedente->siguiente=NuevaArista;
            }
        }
    }
}

//**************************//
//insertar version con dato //
//**************************//

template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::InsertarHijo(pNodo& padre, pNodo& hijo, datoarista_t valorArista, pArista precedente)
{
    pArista nueva = new t_arista(valorArista);
    InsertarHijo(padre, hijo, nueva, precedente);
}

//*******************************************//
//hallar la arista precedente a un nodo dado //
//*******************************************//

template <typename datonodo_t, typename datoarista_t>
arista<datoarista_t,datonodo_t>* Grafo<datonodo_t,datoarista_t>::hallarArista (pNodo& nodopadre, pNodo& nodohijo)
{
    pArista precedente = nullptr;
    if (nodopadre->adyacente)
    {
        precedente= nodopadre->adyacente;
        while(precedente->siguiente)
        {
            if (precedente->destino==nodohijo)
            {
                //std::cout<<"Retorno precedente"<<std::endl;
                return precedente;
            }
            else
            {
                precedente=precedente->siguiente;
            }
        }
    }
    std::cout<<"No retorno nada"<<std::endl;
    return precedente;
}

//**********************************************************************//
//copia un grafo a partir de un nodo dado en una parte del grafo actual //
//**********************************************************************//
template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::Copiar(pNodo& padre, pNodo& hijo, pArista NuevaArista, pArista precedente)
{
    std::cout<<"FUNCION COPIAR "<<padre->datonodo<<"-->"<<hijo->datonodo<<std::endl;
    pArista copianuevaarista = nullptr;
    if (NuevaArista)
    {
        copianuevaarista = new t_arista(*NuevaArista);
    }
    else
    {
        copianuevaarista = new t_arista();
    }
    pNodo copiahijo = posicionarseEnNodo(hijo->datonodo);
    if (!copiahijo)
    {
        copiahijo = new t_nodo(*hijo);
        copiahijo->nPadres--;
    }
    guardaAristasParaCopia(hijo);
    pArista A = padre->adyacente;
    int pos=0;
    while (A && A!=precedente)
    {
        pos++;
        A=A->siguiente;
    }
    Insertar(padre,copiahijo,copianuevaarista,pos);
    while (!pilaAristasParaCopia.empty())
    {
        pArista actual = pilaAristasParaCopia.top();
        pNodo nieto = actual->destino;
        pilaAristasParaCopia.pop();
        std::cout<<"Copia hijo adyacente: "<<copiahijo->adyacente<<std::endl;
        pArista prec = hallarArista(copiahijo,nieto);
        pNodo repadre = posicionarseEnNodo(actual->origen->datonodo);
        if (repadre)
        {
            Copiar(repadre, nieto, actual,prec);
        }
    }
}

//********************************************//
//Crea un grafo a partir de un nodo dado      //
//********************************************//

template <typename datonodo_t, typename datoarista_t>
nodo<datonodo_t,datoarista_t>* Grafo<datonodo_t,datoarista_t>::CrearGrafoAPartirDeNodo(const pNodo& nodo)
{
    pNodo raiz = nullptr;
    if (nodo)
    {
        raiz =  new t_nodo(*nodo);
    }
    Raiz=raiz;//tengo que definir ya la raiz aqui aunque no tenga mucho sentido porque la necesito definida para otras funciones
    guardaAristasParaCopia(nodo);
    while (!pilaAristasParaCopia.empty())
    {
        pArista AristaHijo = pilaAristasParaCopia.top();
        pilaAristasParaCopia.pop();
        Copiar(raiz,AristaHijo->destino,AristaHijo,nodo->adyacente->anterior);
    }

    return raiz;
}

//******************************************//
//recorre toda la lista de nodos del grafo  //
//******************************************//

template <typename datonodo_t, typename datoarista_t>
std::list<nodo<datonodo_t,datoarista_t>*>Grafo<datonodo_t,datoarista_t>::recorrerNodos() const
{
    //nodos.clear();
    std::list<pNodo> nodos;
    if (Raiz)
    {
        pNodo indice = Raiz;
        nodos.push_back(indice);
        while (indice->siguiente)
        {
            indice= indice->siguiente;
            nodos.push_back(indice);
        }
    }
    return nodos;
}

//*************************************//
//recorrer el arbol a partir de un nodo//
//*************************************//

template <typename datonodo_t, typename datoarista_t>
std::list<nodo<datonodo_t,datoarista_t>*>& Grafo<datonodo_t,datoarista_t>::recorrerGrafo(const pNodo& inicio)
{
    VaciarPila(pilaAristas);
    nodos.clear();
    return lista_recorrerGrafo(inicio);
}

template <typename datonodo_t, typename datoarista_t>
std::list<nodo<datonodo_t,datoarista_t>*>& Grafo<datonodo_t,datoarista_t>::lista_recorrerGrafo(const pNodo& inicio)
{
    pArista A;
    if (inicio)
    {
        guardaAristas(inicio);
        while (!pilaAristas.empty())
        {
            A=pilaAristas.top();
            pilaAristas.pop();
            nodos.push_back(A->destino);
            lista_recorrerGrafo(A->destino);
        }
    }
    return nodos;
}

//*********************************************************************//
//busca si un nodo que quiero copiar como hijo de otro es padre de éste//
//necesario para evitar referencias circulares                         //
//*********************************************************************//

template <typename datonodo_t, typename datoarista_t>
bool Grafo<datonodo_t,datoarista_t>::esReferenciaCircular(pNodo& padre, pNodo& hijo)
{
    if (padre==hijo)
    {
        std::cout<<"Referencia $$ circular"<<std::endl;
        return true;
    }
    else
    {
        pArista A;
        bool encontrado=false;
        guardaAristas(hijo);
        while (!pilaAristas.empty())
        {
            A=pilaAristas.top();
            pilaAristas.pop();
            if (A->destino==padre)
            {
                //vacio la pila
                while (!pilaAristas.empty())
                    pilaAristas.pop();
                std::cout<<"Referencia circular"<<std::endl;
                return true;
            }
            return encontrado || esReferenciaCircular(padre,A->destino);
        }
    }
    return false;
}

//*************************************************************//
//comprueba la existencia de un nodo igual al que quiero copiar//
//necesario para evitar tener dos nodos iguales colgando del   //
//mismo padre                                                  //
//*************************************************************//

template <typename datonodo_t, typename datoarista_t>
bool Grafo<datonodo_t,datoarista_t>::existeHermano (pNodo& padre, pNodo& hijo)
{
    pArista A=padre->adyacente;
    while (A!=nullptr)
    {
        //std::cout<<"posicionada la arista"<<A<<std::endl;
        if (A->destino==hijo)
        {
            return true;
        }
        A=A->siguiente;
    }
    return false;
}

//*********************************************//
//comprueba la presencia de un nodo en la lista//
//para evitar su inclusión por duplicado       //
//*********************************************//

template <typename datonodo_t, typename datoarista_t>
bool Grafo<datonodo_t,datoarista_t>::existeNodo (const pNodo& n)
{
    pNodo indice=Raiz;
    if (n==indice)
        return true;
    else
    {
        while (indice->siguiente)
        {
            indice=indice->siguiente;
            if (n==indice)
            {
                return true;
            }
        }
    }
    return false;
}

//***************************************************//
//guarda las aristas que penden de un nodo en la pila//
//***************************************************//

template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::guardaAristas (const pNodo& n)
{
    pArista A;

    if (n && n->adyacente) //si hay aristas
    {
        A=n->adyacente;
        //me posiciono en la última arista
        while (A->siguiente!=nullptr)
        {
            A=A->siguiente;
        }
        //empiezo el recorrido hacia atrás
        while (A->anterior!=nullptr)
        {
            pilaAristas.push (A); //meto la arista en la pila
            A=A->anterior;
        }
        pilaAristas.push (A); //meto la primera arista en la pila*/
    }
}


template <typename datonodo_t, typename datoarista_t>
void Grafo<datonodo_t,datoarista_t>::guardaAristasParaCopia(const pNodo& n)
{
    pArista A;
    if (n && n->adyacente) //si hay aristas
    {
        A=n->adyacente;
        //me posiciono en la última arista
        while (A->siguiente!=nullptr)
        {
            A=A->siguiente;
        }
        while (A->anterior!=nullptr)
        {
            if (A->destino)
                pilaAristasParaCopia.push (A); //meto la arista en la pila
            A=A->anterior;
        }
        if (A->destino)
            pilaAristasParaCopia.push (A); //meto la arista en la pila
    }
}

//*******************************************************************************************************//
//si existe un nodo con el valor a comparar, devolvemos ese nodo. En caso concreto devolvemos valor nulo //
//*******************************************************************************************************//

template <typename DATON, typename DATOA>
nodo<DATON,DATOA>* Grafo<DATON,DATOA>::posicionarseEnNodo(const datonodo_t& dato)
{
    std::cout<<"Buscando el nodo con codigo: "<<dato<<std::endl;
    pNodo indice=Raiz;
    while (indice)// && indice->siguiente)
    {
        if (indice->datonodo == dato)
        {
            return indice;
        }
        indice=indice->siguiente;
    }
    return nullptr;
}

//*********************//
// vaciar la pila dada //
//*********************//

template <typename DATON, typename DATOA>
template <typename T>
void Grafo<DATON,DATOA>::VaciarPila(std::stack<T>& pila)
{
    while (!pila.empty())
    {
        pila.pop();
    }
}

#endif // GRAFO_H

A main.cpp to handle it:

#include <list>
#include <iomanip>

#include "./grafo.h"

typedef char datonodo_t;
typedef int datoarista_t;

typedef nodo<datonodo_t,datoarista_t>* pNodo;
typedef arista<datoarista_t,datonodo_t>* pArista;
typedef nodo<datonodo_t,datoarista_t> t_nodo;
typedef arista<datoarista_t,datonodo_t> t_arista;

void verLista (std::list<pNodo>lista)
{
    for (auto it = lista.begin(); it!=lista.end(); ++it)
    {
        std::cout<<(*it)->datonodo;
    }
    std::cout<<std::endl;
}

void verLista(std::list<std::pair<pNodo,int>>lista)
{
    for (auto it=lista.begin(); it!=lista.end(); ++it)
    {
        std::cout<<std::setw((*it).second)<<"-"<<(*it).first->datonodo<<"-"<<&(*it)<<std::endl;
    }
    std::cout<<std::endl;
}

int main(int argc, char *argv[])
{
    pNodo A = new t_nodo('A');
    pNodo B = new t_nodo('B');
    pNodo C = new t_nodo('C');
    pNodo D = new t_nodo('D');
    pNodo E = new t_nodo('E');
    pNodo F = new t_nodo('F');
    pNodo G = new t_nodo('G');

    pArista AB = new t_arista(20);
    pArista AC = new t_arista(20);
    pArista AD = new t_arista(20);
    pArista BE = new t_arista(20);
    pArista BF = new t_arista(20);
    pArista BG = new t_arista(20);
    //pArista CG = new t_arista(20);

    Grafo<datonodo_t,datoarista_t>g(A);

    g.Insertar(A,B,AB);
    g.Insertar(A,C,AC);
    g.Insertar(A,D,AD,0);
    g.Insertar(B,E,BE);
    g.Insertar(B,F,BF);
    g.Insertar(B,G,BG);
    //g.Insertar(C,G,CG);


    std::cout<<"lista original: ";
    verLista(g.recorrerNodos());
    verLista(g.recorrerGrafo(g.LeeRaiz()));
    std::cout<<"Raiz: "<<g.LeeRaiz()->datonodo<<std::endl;
    Grafo<char,int>g1(g);
    std::cout<<"lista duplicada g1: ";
    verLista(g1.recorrerNodos());
    verLista(g1.recorrerGrafo(g1.LeeRaiz()));
    std::cout<<"Raiz g1: "<<g1.LeeRaiz()->datonodo<<std::endl;

    return 0;
}

If the program runs as it is now (without creating the CG edge or inserting it), there are no memory leakage errors, but if I decompose these last two lines there is. When I invoke the constructor copy of the graph, it traverses the original graph node by node. The idea -in the function Copiar() of the class Grafo is that if in the target graph the node does not exist, it is created and linked to the graph by means of its edges, but if it already exists, it is only linked. It is an implementation of the adjacency list method.

    
asked by user3733164 13.01.2018 в 21:27
source

1 answer

1

The error is found in the way in which the destructor of class Grafo is managed. The reason is that at the moment of deleting one of the nodes it is associated with several edges ... so it is not destroyed in that pass ... and it does not happen again in the future. You can try to debug the code ... it is node number 13 (in order of construction) that is not deleted. The node is in g1 for more signs.

I do not finish understanding the complexity associated with this destructor ... if what you want is to clean the memory, it is exactly the same if invalid pointers remain in the middle of the process ... the grace lies in knowing what is not you have to touch during the deletion process ... those pointers are in elements that are going to be erased an instant later, then their temporary status is irrelevant.

I can think of a cleaner cleaner such that:

#include <set>

template <typename datonodo_t, typename datoarista_t>
Grafo<datonodo_t,datoarista_t>::~Grafo()
{
    std::cout<<"Iniciamos el destructor"<<std::endl;

    std::set<pArista> aristas;

    pNodo nodo = Raiz;
    while( nodo )
    {
      pArista arista = nodo->adyacente;
      while( arista )
      {
        aristas.insert(arista);
        arista = arista->siguiente;
      }

      pNodo temp = nodo->siguiente;
      delete nodo;
      nodo = temp;
    }

    for( pArista arista : aristas )
      delete arista;

    std::cout<<"Borrada la raiz"<<std::endl;
}

Surely with a different design of the class Grafo you get a cleaner cleaner ... but since I do not know the requirements of the project it makes me a little risky to propose more drastic changes.

Also, for readability, I would advise you not to use aliases for pointers. I think it is preferable that the asterisk always appears ... so, for example, you would see that a constant reference to a pointer is somewhat absurd since it does not contribute anything except an additional indirection.

    
answered by 15.01.2018 / 12:05
source