封装两种DirectedGraph结构,在写泛化VDiGraphEx时考虑的不是很周全,一开始犹豫是用Vector还是Array实现对边和结点的打包,考虑到图结构的递归特性,如果用Array对空间消耗较大,另一方面映射表已经解决了时间效率问题,那么非映射表型的图决定采取其互补形式设计.


另一方面,对删除边和结点的时候,需要考虑如何做效率才高,但是主索引list与边和结点并没有相互索引的能力,所以效率不是很高,有重复索引的嫌疑.

0 主要功能已经实现.
1 没有用SmartPtr管理,但是这样也节省了很多中转时间,除了中途为了提高效率直接用指针p索引产生了难以发现的bug外,可预见的范围似乎不会造成内存泄露,因所有数据都被VChain装箱.
2 status和arc都有key,这样方便唯一化数据.
3 实现了部分BFS和DFS,有空需要改进递归实参传值,把参数内置化.另外由于时间问题,写遍历的时候第一个被加进来的结点必须能到达其他所有结点,有空再把循环索引内容实现,实现广义上的图遍历.


有空还需要去借鉴下其他比较好的实现,欢迎各位来散步的指出不足之处,非常感谢.

#ifndef VG_GRAPH

#define VG_GRAPH


#include 
"VGMatrix.h"
#include 
"VGArray.h"
#include 
"VGChain.h"

namespace VGAdt
{

    
using VGAdt::VArray;
    template
<typename VTypeN,typename VTypeE=VTypeN>
    
class VDiGraph:public VGBase::VAdt
    
{
    
public:
        VGMatrix
<VTypeE> graArr;
        VArray
<VTypeN> nodeValue;
        
int nodeNum;
        
int maxNum;
        VDiGraph(
int maxNum_,VTypeE z,VTypeE o)
        
{
            nodeNum
=0;
            maxNum
=maxNum_;
            graArr.setKey(z,o);
            graArr.rebirth(maxNum,maxNum);
        }

        
int addNode(VTypeN value_)
        
{
            nodeValue[nodeNum]
=value_;
            
++nodeNum;
        }

        
int setValue(int i_,VTypeN value_)
        
{
            
if(i_>=nodeNum)
            
{
                i
=nodeNum;
                
++nodeNum;
            }
else if(i_<=-1)
            
{
                
return 0;
            }

            nodeValue[i_]
=value_;
            
return 1;
        }

        
int setArc(int i_,int j_,VTypeE weights)
        
{
            
if(i_>=maxNum||j_>=maxNum)
            
{
                
return 0;
            }

            
if(i_>=nodeNum||j_>=nodeNum)
                
++nodeNum;
            graArr[i_][j_]
=weights;
            
return 1;
        }

        VTypeE isGo(
int i_,int j_)
        
{
            
if(graArr[i_][j_]==graArr.VOne_)
            
{
                
return graArr.VOne_;
            }
else
            
{
                
return graArr[i_][j_];
            }

        }

        
int isGoBy(int i_,VTypeE w_)
        
{
            
for(int i=0;i!=nodeNum;i++)
            
{

                if(graArr[i_][i]==w_)
                    
return i;
            }

            
return -1;
        }

        VArray
<VTypeE>& operator [](int i_)
        
{
            
return graArr[i_];
        }



    }
;
    
using VGAdt::VChain;
    template
<typename VTypeN,typename VTypeE=VTypeN>
    
class VDiGraphEx :public VGBase::VAdt
    
{
    
public:
        
struct VEdge;
        
struct VStatus;
        
struct VArc
        
{
            VStatus 
* end;
            VStatus 
* start;
            VTypeE value;
            
int key;

        }
;
        
struct VStatus
        
{
            VChain
<VArc*> inArc;
            VChain
<VArc*> outArc;
            VTypeN value;
            
int key;
            VStatus
* findOut(int key_)
            
{
                outArc.p
=outArc.head->next;
                
for(int i=0;i!=outArc.size;i++)
                
{
                    
if(outArc.p->elem->end->key==key_)
                    
{
                        
return outArc.p->elem->end;
                    }

                    outArc.p
=outArc.p->next;
                }

                
return 0;
            }

            
int delArc(VStatus* s_)
            
{
                
for(int i=0;i!=inArc.size;i++)
                
{
                    
if(inArc[i]->end==s_||inArc[i]->start==s_)
                    
{
                        delete inArc[i];
                        inArc.Del(i);
                        
--i;
                    }

                }

                
return 1;
            }

        }
;
        
int vNum;
        
int eNum;
    
public:
        VStatus 
* src;
        VStatus 
* pos;
        VChain
<VStatus*> statusList;
        VChain
<VArc*> arcList;
        VDiGraphEx()
        
{
            vNum
=0;
            eNum
=0;
            src
=pos=0;

        }

        
~VDiGraphEx()
        
{
            emptyArcs();
            emptyStatus();
        }

        
int isGo(int key_start,int key_end)
        
{
            VStatus 
* state_start=(*this)[key_start];
            
if(state_start->findOut(key_end))
            
{
                
return 1;
            }
else
            
{
                
return 0;
            }


        }

        
int addStatus(int key_,VTypeN value_)
        
{
            
if(isNull(key_))
            
{
                statusList.Insert(vNum
++,new VStatus);
                statusList[vNum
-1]->value=value_;
                statusList[vNum
-1]->key=key_;
                
return 1;
            }

            
return 0;
        }

        
int addArc(int key_start,int key_end,VTypeE value_)
        
{
            
if(isNull(key_start)||isNull(key_end))
                
return 0;
            VArc 
* _arc = new VArc;
            _arc
->start=(*this)[key_start];
            _arc
->end=(*this)[key_end];
            _arc
->value=value_;
            _arc
->start->outArc.Push(_arc);
            _arc
->end->inArc.Push(_arc);
            arcList.Push(_arc);
            
++eNum;
            
return 1;
        }

        
int delStatus(int key_)
        
{
            statusList.p
=statusList.head->next;
            
for(int i=0;i!=vNum;i++)
            
{
                
if(statusList.p->elem->key==key_)
                
{



                    
for(int j=0;j!=arcList.size;j++)
                    
{

                        VArc
* _arc=arcList[j];

                        
if(_arc->end==statusList.p->elem)
                        
{
                            _arc
->end->delArc(statusList.p->elem);
                            arcList.Del(j);
                            
--eNum;

                            
--j;

                        }
else if(statusList.p->elem==_arc->start)
                        
{
                            _arc
->start->delArc(statusList.p->elem);
                            arcList.Del(j);
                            
--eNum;
                            
--j;

                        }



                    }


                    statusList.Del(i);
                    
--vNum;

                    
return 1;
                }

                statusList.p
=statusList.p->next;
            }

            
return 0;
        }

        
int isNull(int key_)
        
{
            statusList.p
=statusList.head->next;
            
for(int i=0;i!=vNum;i++)
            
{
                
if(statusList.p->elem->key==key_)
                
{
                    
return 0;
                }

                statusList.p
=statusList.p->next;
            }

            
return 1;
        }

        
int emptyArcs()
        
{
            
for(int i=0;i!=eNum;i++)
            
{

                delete arcList[
0];
                arcList.Del(
0);
            }

            
return 1;
        }

        
int emptyStatus()
        
{

            
for(int i=0;i!=vNum;i++)
            
{
                delete statusList[
0];
                statusList.Del(
0);
            }

            
return 1;
        }

        VStatus
* operator [](int key_)
        
{
            statusList.p
=statusList.head->next;
            
for(int i=0;i!=vNum;i++)
            
{
                
if(statusList.p->elem->key==key_)
                
{
                    
return statusList[i];
                }

                statusList.p
=statusList.p->next;
            }

            
return 0;
        }

        
int travelDFS(VStatus * pos_,VTypeN * value_list,VStatus * adr_list[],int& len)
        
{
            
if(len==0)
            
{
                
if(vNum>=1)
                
{
                    value_list[
0]=statusList[0]->value;
                    
++len;
                    adr_list[
0]=statusList[0];
                    
for(int j=0;j!=statusList[0]->outArc.size;j++)
                        travelDFS(statusList[
0]->outArc[j]->end,value_list,adr_list,len);
                }

                
return 1;
            }

            
for(int i=0;i!=len;i++)
                
if(pos_==adr_list[i])
                    
return 1;

            adr_list[len]
=pos_;
            value_list[len]
=pos_->value;
            
++len;
            
for(int i=0;i!=pos_->outArc.size;i++)
                travelDFS(pos_
->outArc[i]->end,value_list,adr_list,len);

            
return 1;

        }

        
int travelSubBFS(VStatus * pos_,VTypeN * value_list,VStatus * adr_list[],int& len)
        
{

            
for(int i=0;i!=len;i++)
                
if(pos_==adr_list[i])
                    
return 1;

            adr_list[len]
=pos_;
            value_list[len]
=pos_->value;
            
++len;

            
return 1;

        }

        
int travelBFS(VStatus * pos_,VTypeN * value_list,VStatus * adr_list[],int& len)
        
{

            value_list[
0]=statusList[0]->value;
            
++len;
            adr_list[
0]=statusList[0];
            
for(int j=0;j!=statusList[0]->outArc.size;j++)
                travelSubBFS(statusList[
0]->outArc[j]->end,value_list,adr_list,len);

            
int last_len=1,len_buf;
            
for(;;)
            
{
                len_buf
=len;
                
for(int i=last_len;i!=len;i++)
                    
for(int j=0;j!=adr_list[i]->outArc.size;j++)
                        travelSubBFS(adr_list[i]
->outArc[j]->end,value_list,adr_list,len);
                
if(len==vNum)
                    
return 1;
                last_len
=len_buf;

            }

        }

    }
;


}
;





#endif





VDiGraph的case:
    VDiGraph<int,char> a(20,0,1);
    a.setArc(
0,1,'a');
    a.setArc(
0,2,'c');
    a.setArc(
1,3,'b');
    a.setArc(
2,3,'d');
    a.setArc(
3,4,'e');
    
while(1){
    
char get;
    
int i=0,j=0;
    
for(;i!=3;i++){
       cin
>>get;
       
if((j=a.isGoBy(j,get))==-1)break;
    }

    
if(i==3) cout<<"your input matchs my dfa!\n";
    }


VDiGraphEx的case:

    using VGAdt::VDiGraphEx;

    VDiGraphEx
<char,char>  a;

    a.addStatus(
1,'h');
    a.addStatus(
2,'e');
    a.addStatus(
3,'l');
    a.addStatus(
4,'l');
    a.addStatus(
5,'o');
    a.addStatus(
6,'i');
    a.addStatus(
7,'j');
    a.addStatus(
8,'8');
    a.addStatus(
9,'9');
    a.addStatus(
10,'a');
    a.addStatus(
11,'b');
    
    a.addArc(
1,2,'1');
    a.addArc(
2,3,'2');
    a.addArc(
3,4,'3');
    a.addArc(
4,5,'4');
    a.addArc(
1,3,'5');
    a.addArc(
1,5,'6');
    a.addArc(
1,6,'7');
    a.addArc(
2,3,'8');
    a.addArc(
6,7,'8');
    a.addArc(
6,8,'8');
    a.addArc(
6,9,'8');
    a.addArc(
8,10,'8');
    a.addArc(
8,11,'8');
    int len=0;
    VDiGraphEx
<char,char>::VStatus * adr_list[100];
char value_list[100]={0};
    a.travelBFS(0,value_list,adr_list,len);
    cout
<<value_list<<":"<<len<<endl;