邻接多重表结构主要针对的是无向图进行的存储优化。详细概念可百度谷歌下。如果我们在无向图的应用中,关注的重点是顶点,那么邻接表是不错的选择,但如果我们更关注边的操作,比如对已访问过的边做标记,删除某一条边等操作,那就意味着,需要找到这条边的两个边表结点进行操作,这其实还是比较麻烦的。因此,我们也依照十字链表的方式,对表结点进行一下改造:
[ ivex | ilink | jvex | jlink]
其中ivex和jvex是与某条边依附的两个顶点在顶点表中下标。ilink指向依附点ivex的下一条边,jlink指向依附点jvex的下一条边,这就是邻接多重表结构。关于邻接多重表的一些相关操作,多数网站上都没有具体的介绍,本人的代码主要参考严魏敏的 <数据结构>,但是本书中提供的代码有一定的问题(尤其是删除节点及其相关的边这一函数,弄了很长时间才把问题找出来并改正,神坑啊),以下是改正后的代码,我又添加了一些基本功能,希望可以给大家参考下:
在MulAdjGraph.h文件中:
/********************************* 声明区 ****************************/
typedef enum{unmarked,marked}MarkedIf;
typedef int VertexType; // 图节点标识号
typedef int QElemType;
/********************************* 数据结构体 ****************************/
typedef struct ArcType
{
int ivex,jvex; // 该边依附的两个顶点的位置
struct ArcType *ilink,*jlink; // 分别指向依附这两个顶点的下一条边
MarkedIf mark; // 访问标记
float weight; // 权重
inline ArcType(): ivex(-1),jvex(-1),mark(unmarked),weight(0) {}
}ArcType;
typedef struct VertexNode
{
VertexType data;
bool isVisited; // 访问标记
ArcType *firstarc; // 指向第一条依附该顶点的边
inline VertexNode():data(-1),isVisited(false) {}
}VertexNode;
typedef struct MulAdjGraph
{
VertexNode *adjmulist; // 多重邻接表
int ivexNum,iarcNum; // 无向图的当前顶点数和边数
int MaxVertexNum; // 表中最大的节点数量
MulAdjGraph(): ivexNum(0), iarcNum(0),MaxVertexNum(0) {}
}MulAdjGraph;
// 单链队列--队列的链式存储结构
typedef struct QNode
{
QElemType data; //数据域
struct QNode *next; //指针域
}QNode,*QueuePtr;
typedef struct
{
QueuePtr front,//队头指针,指针域指向队头元素
rear; //队尾指针,指向队尾元素
}LinkQueue;
/********************************* 基本操作函数 ****************************/
// 若G中存在顶点u,则返回该顶点在无向图中位置;否则返回-1
int LocateVex( const MulAdjGraph &G,const VertexType &u );
// 采用邻接多重表存储结构,构造无向图G
int CreateGraph(MulAdjGraph &G);
// 返回v的值
inline VertexType* GetVex(const MulAdjGraph &G,const int &v);
// 对v赋新值value
int PutVex(MulAdjGraph &G,const VertexType v,const VertexType &value);
// 返回v的第一个邻接顶点的序号。若顶点在G中没有邻接顶点,则返回-1
int FirstAdjVex(const MulAdjGraph &G,const VertexType &v);
// 返回v的(相对于w的)下一个邻接顶点的序号。若w是v的最后一个邻接点,则返回-1
int NextAdjVex(const MulAdjGraph &G,const VertexType &v,const VertexType &w);
// 在G中增添新顶点v(不增添与顶点相关的弧,留待InsertArc()去做)
int InsertVex(MulAdjGraph &G,const VertexType v);
// 在G中删除弧<v,w>
int DeleteArc(MulAdjGraph &G,const VertexType &v,const VertexType &w);
// 删除G中顶点v及其相关的边
int DeleteVex(MulAdjGraph &G,const VertexType &v);
void DestroyGraph(MulAdjGraph &G);
// 在G中增添弧<v,w>
int InsertArc(MulAdjGraph &G,const VertexType &v,const VertexType &w);
//搜索弧<v,w>是否存在
bool SearchArc(const MulAdjGraph &G,const VertexType &v,const VertexType &w);
//找到顶点v的邻接顶点,函数返回符合条件的顶点数目
int FindNeighbour(const MulAdjGraph &G,const VertexType &v,VertexType *s);
extern int(*VisitFunc)(const VertexType &v);
void DFS(MulAdjGraph &G,int v);
// 算法7.4
// 从第1个顶点起,深度优先遍历图G,并对每个顶点调用函数Visit
void DFSTraverse(MulAdjGraph