7.2 图的存储结构
7.2.3 邻接多重表(多重邻接表)Adjacency Multilist
在无向图的邻接表中可以看到,每一条边(vi,vj)在邻接表中有两个边结点:一个在顶点vi的边链表中,表示(vi,vj);一个在顶点vj的边链表中,表示(vj,vi)。
在较复杂的问题中,有时需要给被处理的边加标记(如访问标志或删除标志等),若用邻接表表示,则需要同时给表示某一条边的两个边结点加标记,而这两个结点又不在同一个边链表中,所以处理会很不方便。若改用邻接多重表作为无向图的存储表示,则可简化上述问题的处理。
邻接多重表的类定义
邻接多重表的顶点结点类模板
对图中的每一个顶点用一个顶点结点表示,它有两个域组成,其中:
data域存储有关顶点的信息;
firstarc域是链接指针,指向第一条依附于该顶点的边。
所有的顶点结点组成一个顺序表。
template <class ElemType ,class WeightType>
class MultiAdjListNetworkVex
{
public:
ElemType data;
MultiAdjListNetworkArc<WeightType> *firstarc;
MultiAdjListNetworkVex()
{
firstarc = NULL;
}
MultiAdjListNetworkVex(ElemType val, MultiAdjListNetworkArc<WeightType>* adj = NULL)
{
data = val;
firstarc = adj;
}
};
邻接多重表的边结点类模板
在无向图的邻接多重表中,图的每一条边用一个边结点表示,它由六个域组成,其中:
tag是标记域,标记该边是否被处理或被搜索过;
weight为边的信息域,用于存储边的权值;adjvexl和adjvex2是顶点域,表示该边所依附的两个顶点在图中的序号;
nextarcl1域是链接指针,指向下一条依附于顶点adjvexl的边;
nextarc2也是链接指针,指向下一条依附于顶点adjvex2的边。
template <class WeightType>
class MultiAdjListNetworkArc
{
public:
int mark; //标记该边是否被搜索或处理过
WeightType weight; //边的权重
int adjVex1; //边的一个顶点
MultiAdjListNetworkArc<WeightType>* nextarc1; //指向下一条依附于adjvex1的边,eg:1-2-->1-3-->5-1
int adjVex2;
MultiAdjListNetworkArc<WeightType>* nextarc2;
MultiAdjListNetworkArc()
{
adjVex1= -1;
adjVex2= -1;
}
MultiAdjListNetworkArc(int v1, int v2, WeightType w, MultiAdjListNetworkArc<WeightType>* next1 = NULL,MultiAdjListNetworkArc<WeightType>* next2 = NULL)
{
adjVex1 = v1; adjVex2 = v2;
weight = w;
nextarc1 = next1; nextarc2=next2;
mark = 0; //0表示未被搜索,1表示被搜索过
}
邻接多重表的类模板
1.类定义
template <class ElemType,class WeightType>
class MultiAdjListNetwork
{
protected:
int vexNum, vexMaxNum, arcNum;
MultiAdjListNetworkVex<ElemType, WeightType>* vexTable;
int* tag;
WeightType infinity;
public:
MultiAdjListNetwork(ElemType es[], int vertexNum,int vertexMaxNum= DEFAULT_SIZE, WeightType infinit = (WeightType)DEFAULT_INFINITY);
MultiAdjListNetwork(int vertexMaxNum = DEFAULT_SIZE, WeightType infinit = (WeightType)DEFAULT_INFINITY);
void Clear();
bool IsEmpty()
{
return vexNum == 0;
}
int GetArcNum()const
{
return arcNum;
}
int GetvexNum()const
{
return vexNum;
}
int FirstAdjVex(int v)const;
int NextAdjVex(int v1, int v2)const;
MultiAdjListNetworkArc<WeightType>* NextArc(int v1,MultiAdjListNetworkArc<WeightType>*p)const;
MultiAdjListNetworkArc<WeightType>* LastArc(int v1,MultiAdjListNetworkArc<WeightType>*p)const;
void InsertVex(const ElemType& d);
void InsertArc(int v1, int v2, WeightType w);
void DeleteVex(const ElemType& d);
void DeleteArc(int v1, int v2);
MultiAdjListNetwork(const MultiAdjListNetwork<ElemType, WeightType>* copy);
MultiAdjListNetwork<ElemType, WeightType> &operator=(const MultiAdjListNetwork<ElemType, WeightType>& copy);
///深度优先遍历
void DFS1(const int v);
void DFS1Traverse();
void DFS2();
int GetAdjVex(int head,int pre);//从顶点v出发的一个顶点u,返回v通往的下一个顶点;如果没有其它分支或者已经是最后一个连通点,返回-1;如果要取第一个顶点传入-1
void DFS3();
void BFS();
void Show();
};
2.函数的实现
研讨题,能够运行,但是代码不一定是最优的。
#include <stack>
#include <queue>
template <class ElemType,class WeightType>
MultiAdjListNetwork<ElemType,WeightType>::MultiAdjListNetwork(ElemType es[],int vertexNum,int vertexMaxNum,WeightType infinit)
{
if(vertexMaxNum < 0)
throw Error("允许的顶点最大数目不能为负!");
if (vertexMaxNum < vertexNum)
throw Error("顶点数目不能大于允许的顶点最大数目!");
vexNum = vertexNum;
vexMaxNum = vertexMaxNum;
arcNum = 0;
infinity = infinit;
tag = new int[vexMaxNum];
vexTable = new MultiAdjListNetworkVex<ElemType, WeightType>[vexMaxNum];
for (int v = 0; v < vexNum; v++)
{
tag[v] = 0;
vexTable[v].data = es[v];
vexTable[v].firstarc = NULL;
}
}
template <class ElemType,class WeightType>
MultiAdjListNetwork<ElemType,WeightType>::MultiAdjListNetwork(int vertexMaxNum, WeightType infinit)
{
if (vertexMaxNum < 0)
throw Error("允许的顶点最大数目不能为负!");
vexNum = 0;
vexMaxNum = vertexMaxNum;
arcNum = 0;
infinity = infinit;
tag = new int[vexMaxNum];
vexTable = new MultiAdjListNetworkVex<ElemType, WeightType>[vexMaxNum];
}
template<class ElemType, class WeightType>
int MultiAdjListNetwork<ElemType