#ifndef GRAFO_H
#define GRAFO_H
#include <stack>
#include <list>
#include <utility>
#include "Functores.h"
class TratarArista;
class TratarNodo;
class TratarAristaConNiveles;
class ImprimirArbol;
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=0, arista<DATOA, DATON>* a=0):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=0;
adyacente=0;
}
//destructor
~nodo()
{
siguiente=0;
adyacente=0;
//borrar pila?
//borrar datonodo?
std::cout<<"Destructor nodo"<<std::endl;
}
//operador de asignacion
nodo& operator = (const nodo<DATON, DATOA>& n)
{
if (this!=&n)
{
datonodo=n.datonodo;
nPadres=n.nPadres;
siguiente=0;
adyacente=0;
}
return *this;
}
};
template <typename DATOA, typename DATON>
struct arista
{
DATOA datoarista;
nodo<DATON,DATOA>* destino;
arista<DATOA,DATON>* siguiente;
arista<DATOA,DATON>* anterior;
//constructores
arista(DATOA A=0, nodo<DATON,DATOA>* d=0, arista<DATOA,DATON>* s=0, arista<DATOA,DATON>* an=0):datoarista(A),destino(d),siguiente(s), anterior(an) {}
arista (const arista<DATOA,DATON>& a)
{
datoarista=a.datoarista;
destino=0;
siguiente=0;
anterior=0;
}
//operador de asignacion
arista& operator = (const arista<DATOA, DATON>& a)
{
if (this!=&a)
{
datoarista=a.datoarista;
destino=0;
siguiente=0;
anterior=0;
}
return *this;
}
};
template <typename DATON, typename DATOA>
class Grafo
{
public:
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;
//constructor
Grafo():Raiz(0),nNodos(0) {std::cout<<"Constructor grafo"<<std::endl;}
//constructor copia
Grafo (const Grafo& G);
//sobrecarga del operador =
Grafo& operator=(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);
/*********insertar,eliminar,copiar elementos del grafo*******************/
void InsertarHijo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista);
void borrarNodos(pArista& A);
void CopiarNodo(pNodo& padre, pNodo& hijo, pArista& precedente, pArista& NuevaArista);
/******funciones para recorrer el grafo*************************/
void recorrerHijos(const pNodo& padre, TratarArista& tratamiento);
void recorrerGrafo(pNodo& inicio, TratarArista& tratamiento);
void recorrerGrafoConNiveles(pNodo& inicio, TratarAristaConNiveles& tratamiento, int n=0);
void recorrerAncestros(pNodo& n,TratarNodo& tratamiento);
void recorrerNodos(TratarNodo& tratamiento);
/**********comprobaciones necesarias****************/
bool esReferenciaCircular(pNodo& padre, pNodo& hijo);
bool existeHermano (pNodo& padre, pNodo& hijo);
bool existeNodo (const pNodo& n);
/***********otras*******************************/
void guardaAristas (pNodo& n);
void guardaAristasNivel (pNodo& n, int nivel);
pNodo posicionarseEnNodo(datonodo_t dato);
/***********consultoras*************************/
int LeeNumNodos()const {return nNodos;}
int NivelNodoPadre(pNodo& padre) const;
/****************funciones para la lista de hojas********************/
//poner aqui
//Destructor
~Grafo();
//private:
pNodo Raiz;
int nNodos;
std::stack<pArista> pila;
std::stack<std::pair<pArista,int> >pilaniveles;
std::list<pNodo>listaHojas;
};