1 图的大类定义
template<class TypeOfVer,class TypeOfEdge>//边的个数即邻接矩阵中有元素的个数
class graph{
public:
virtual void insert(TypeOfVer x,TypeOfVer y,TypeOfEdge w)=0;//w有权重,在结点x,y之间插入一条边
virtual void remove(TypeOfVer x,TypeOfVer y)=0;//在结点x,y之间删除一条边
virtual bool exist(TypeOfVer x,TypeOfVer y)const=0;//结点x,y之间是否存在一条边
int numOfVer()const{return Vers;}//返回结点的数量
int numOfEdge()const{return Edges;}//返回边的数量
protected:
int Vers,Edges;}
2 图的顺序存储–用邻接矩阵储存图
包括为图增加或者减少边,判断两个结点间有没有边的存在
//顺序存储
template<class TypeOfVer,class TypeOfEdge>
class adjMatrixGraph:public graph<TypeOfVer,TypeOfEdge>{
public:
adjMatrixGraph(int vSize,const TypeOfVer d[],const TypeOfEdge noEdgeFlag);
//继承一些接口
void insert(TypeOfVer x,TypeOfVer y,TypeOfEdge w);//w有权重,在结点x,y之间插入一条边
void remove(TypeOfVer x,TypeOfVer y);//在结点x,y之间删除一条边
bool exist(TypeOfVer x,TypeOfVer y)const;//结点x,y之间是否存在一条边
~adjMatrixGraph();
private:
TyprOfEdge **edge;//在二维数组中存放邻接矩阵
TypeOfVer *ver;//存放结点值,位置i存放第i个结点
TypeOfEdge noEdge;//邻接矩阵中无穷大的表示值,表示这两个结点间无连接
int find(TypeOfVer v)const{//返回结点名字叫v的下标
for(int i=0;i<Vers;i++) if(ver[i]==v) return i;
}//这里有两个东西,一个是存放结点值的数组,一个是邻接矩阵
}
template<class TypeOfVer,class TypeOfEdge>
adjMatrixGraph<TypeOfVer,TypeOfEdge>::adjMatrixGraph
(int vSize,const TypeOfVer d[],TypeOfEdge noEdgeFlag)
{
int i,j;
Vers=vSize;//结点数量
Edges=0;//边的数量
noEdge=noEdgeFlag;
//存放结点的数组初始化
ver=new TypeOfVer[vSize];
for(int i=0;i<Vers;i++) ver[i]=d[i];
//邻接矩阵初始化
edge=new TypeOfEdge*[vSize];
for(i=0;i<Vers;i++)
{
edge[i]=new TypeOfEdge[vSize];
for(j=0;j<vSize;j++) edge[i][j]=noEdge;
}
}
template<class TypeOfVer,class TypeOfEdge>
adjMatrixGraph<TypeOfVer,TypeOfEdge>;;~adjMatrixGraph()
{
delete[]ver;
for(int i=0;i<Vers;i++) delete[]edge[i];
delete[]edge;
}
template<class TypeOfVer,class TypeOfEdge>
void adjMatrixGraph<TypeOfVer,TypeOfEdge>::
insert(TypeOfVer x,TypeOfVer y,TypeOfEdge w)
{
int u=find(x),v=find(x);//找到x,y下标
edge[u][v]=w;
++Edges;
}
template<class TypeOfVer,class TypeOfEdge>
void adjMatrixGraph<TypeOfVer,TypeOfEdge>::
remove(TypeOfVer x,TypeOfVer y)
{
int u-find(x),v=find(y);
edge[u][v]=noEdge;
--Edges;
}
template<class TypeOfVer,class TypeOfEdge>
bool adjMatrixGraph<TypeOfVer,TypeOfEdge>::
exist(TypeOfVer x,TypeOfVer y)const
{
int u=find(x),v=find(y);
if(edge[u][v]!=noEdge) return true;
else return false;
}
此处检索两个结点之间有无边和边权重时,只需要看A[i][j]时间复杂度为O[1]
但图的空间复杂度比较高,因为一般图的存储比较稀疏,空间复杂度为O[n**2],因此之后换成邻接表非常有必要。
3 图的链式存储–邻接表
//图的链式存储--邻接表
template<class TypeOfVer,class TypeOfEdge>
class adjListGraph:public graph<TypeOfVer,TypeOfEdge>
{
public:
adjListGraph(int vSize,const TypeOfVer d[]);
//继承一些接口
void insert(TypeOfVer x,TypeOfVer y,TypeOfEdge w);//w有权重,在结点x,y之间插入一条边
void remove(TypeOfVer x,TypeOfVer y);//在结点x,y之间删除一条边
bool exist(TypeOfVer x,TypeOfVer y)const;//结点x,y之间是否存在一条边
~adjListGraph();
private:
struct edgeNode //邻接表中存储边的结点类,挂在结点上的单链表
{
int end;//终点编号
TypeOfEdge weight;
edgeNode*next;
edgeNode(int e,TypeOfEdge w,edgeNode*n=NULL)
{
end=e;
weight=w;
next=n;
}
};
struct verNode
{
TypeOfVer ver;//结点的值
edgeNode*head;//边表表头,单链表表头
verNode(edgeNode*h=NULL)
{
head=h;
}
};
verNode*verList;//唯一属性,结点表的数组
int find(TypeOfVer v)const{
for(int i=0;i<Vers;i++)
if(verList[i].ver==v) return i;
}
}
template<class TypeOfVer,class TypeOfEdge>
adjListGraph<TypeOfVer,TypeOfEdge>::adjListGraph(int vSize,const TypeOfVer d[])
{
Vers=vSize;
Edges=0;
verList=new verNode[vSize];
for(int i=0;i<Vers;i++) verList[i]=d[i];//将传入数字赋值进对应结点表
//以上是结点表的初始化
}
template<class TypeOfVer,class TypeOfEdge>
adjListGraph<TypeOfVer,TypeOfEdge>::~adjListGraph
{
edgeNode*p;
for(int i=0;i<Vers;i++)
{
while(verNode[i].head!=NULL)
{
p=verNode[i].head;
verNode[i].head=p->next;
delete p;
}//在每个位置上删除单链表
}
delete[]verList;
}
template<class TypeOfVer,class TypeOfEdge>
void adjListGraph<TypeOfVer,TypeOfEdge>::insert(TypeOdVer x,TypeOfVer y,TypeOfEdge w)
{
int u=find(x),v=find(y);
verList[u].head=new edgeNode(v,w,verList[u].head);//插到表头
++Edges;
}
template<class TypeOfVer,class TypeOfEdge>
void adjListGraph<TypeOfVer,TypeOfEdge>::remove(TypeOfVer x,TypeOfVer y)
{
int u=find(x),v=find(y);
edgeNode*p=verList[u].head;
if(p==NULL) return;
//如果单链表第一个结点就是被删除的
if(p->end==v)
{
verList[u].head=p->next;
delete p;
return;
}
//如果单链表中间有被删除元素
while(p->next!=NULL&&p->next->end!=v)
{
p=p->next;
}
//让p停在对应结点前一个
edgeVer*q;
q=p->next;
p->next=q->next;
delete q;
--Edges;
}
template<class TypeOfVer,class TypeOfEdge>
bool adjListGraph<TypeOfVer,TypeOfEdge>::exist(TypeOfVer x,TypeOfVer y)
{
int u=find(x),v=find(y);
edgeNode*p=verList[u].head;
while(p->end!=v)
{
p=p->next;
if(p==NULL) return false;
}
return true;
}
关键还是一些单链表的操作,如删除一个结点时,指针停在上一个结点