#include<iostream>
#include<math.h>
using namespace std;
#include"set.h"

             
template <class _ndatatype,class _edatatype>
class NODE;

template <class _ndatatype,class _edatatype>
class EDGE
{
      public:
             _edatatype data;
             NODE <_ndatatype,_edatatype> *start,*end;
             EDGE * parallel;
};

template <class _ndatatype,class _edatatype>
class NODE
{
      public:
             _ndatatype data;
             SET<EDGE<_ndatatype,_edatatype>* > edges;
      EDGE<_ndatatype,_edatatype>* & edge(int index)
      {
                                   return edges[index];
      }
      
};
template <class _ndatatype,class _edatatype>
class GRAPH
{
      public:
             SET<EDGE<_ndatatype,_edatatype> > edges;
             SET<NODE<_ndatatype,_edatatype> > nodes;
      NODE<_ndatatype,_edatatype>& node(int index)
      {
                                   return nodes[index];
      }
      EDGE<_ndatatype,_edatatype>& edge(int index)
      {
                                   return edges[index];
      }
      
      
      int addnode(_ndatatype nodedata)
      {
          NODE<_ndatatype,_edatatype> t;
          t.data=nodedata;      
          return nodes.add(t);
      }
      int addnode()
      {
          return nodes.freeadd();
      }
      
      int addedge(_edatatype edgedata)
      {
          EDGE<_ndatatype,_edatatype> t;
          t.data=edgedata;
          return edges.add(t);
      }
      int addedge()
      {
          EDGE<_ndatatype,_edatatype> t;
          return edges.add(t);
      }
      
      int fullconnect(NODE<_ndatatype,_edatatype> &node1,NODE<_ndatatype,_edatatype> &node2,EDGE<_ndatatype,_edatatype> &edge1,EDGE<_ndatatype,_edatatype> &edge2)
      {
          node1.edges.add(&edge1);
          node2.edges.add(&edge2);
          edge1.start=edge2.end=&node1;
          edge1.end=edge2.start=&node2;
          edge1.parallel=&edge2;
          edge2.parallel=&edge1;
      }
      int connect(NODE<_ndatatype,_edatatype> &node1,NODE<_ndatatype,_edatatype> &node2,EDGE<_ndatatype,_edatatype> &tedge)
      {
          // no previous checking
          node1.edges.add(&tedge);
//          node2.edges.add(&tedge);
          tedge.start=&node1;
          tedge.end=&node2;
      }
      
      int connect(NODE<_ndatatype,_edatatype> &node1,NODE<_ndatatype,_edatatype> &node2)
      {
          return connect(node1,node2,edges[edges.add()]);
      }
      int connect(NODE<_ndatatype,_edatatype> &node1,NODE<_ndatatype,_edatatype> &node2,int edgeindex)
      {
          return connect(node1,node2,edges[edgeindex]);
      }
      int connect(int nodeindex1,int nodeindex2,int edgeindex)
      {
          return connect(nodes[nodeindex1],nodes[nodeindex2],edges[edgeindex]);
      }
      int connect(int nodeindex1,int nodeindex2)
      {
          return connect(nodes[nodeindex1],nodes[nodeindex2],edges[edges.add()]);
      }

      int fullconnect(int nodeindex1,int nodeindex2)
      {
          return fullconnect(nodes[nodeindex1],nodes[nodeindex2],edges[edges.add()],edges[edges.add()]);
      }


      int find(_ndatatype tdata)
      {
          
      }      
      GRAPH()
      {
             
             
      }
};

class mynode
{
      public:
       int data,no;
       int flag;
       mynode()
       {
                   flag=0;
                   static int t=0;
                   data=no=t++;
       }
       mynode operator =(mynode target)
       {
              data=target.data;
              no=target.no;
              flag=target.flag;
       }
};

int main()
{
    GRAPH <mynode,char>g;
    
    g.addnode();
    g.addnode();
    g.addnode();
    g.addnode();
    g.fullconnect(0,1);
    g.fullconnect(1,2);
    g.connect(0,2);

    int i,j;

    for (i=0;i<g.nodes.count;++i)
        g.nodes[i].data.no=i;
    
    for (i=0;i<g.nodes.count;++i)
    {
        cout <<"Node index "<<i<<" exists with data "<<g.nodes(i).data.no<<" & bonds using "<<g.nodes(i).edges.count<<" edges."<<endl;
        for(j=0;j<g.node(i).edges.count;++j)
                                            cout <<"  --Node index "<<i<<" data "<<g.node(i).data.no<<" has edge ("<<j<<") to node with data " << g.nodes(i).edges(j)->end->data.no <<endl;
    }
    

    system("pause");
    return 0;
}      
