封装两种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;
|