使用邻接矩阵有它的优点:易于求结点度,求邻接点,易判断两点间是否有弧相连。但不利于稀疏图的存储,因弧不存在时也要存储相应信息。且要预分配足够大空间。
下面来介绍使用邻接表的方式来存储图。
在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的结点表示依附与顶点vi的边,对有向图是以顶点vi为尾的弧。每个顶点以3个域组成,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的结点,数据域(Info)存储和边或弧相关的信息,如权值等。每个链表上附设一个表头结点。在表头结点中,除了设有链域(firstarc)指向链表中第一个结点之外,还设有存储顶点vi的名或其他有关信息的数据域(data)。
首先是辅助宏的定义:
#define OK 1
#define ERROR 0
#define TRUE 1
#define FALSE 0
#define OVERFLOW -1
#define UNDERFLOW -2
#define MAX_INFO 50
#define MVNUM 100
#define maxn 100
#define maxm 100
#define INFINITY 32767 //一定要很大
typedef int Status;
typedef char VertexType;
typedef char InfoType;
typedef enum{DG,DN,UDG,UDN} GraphKind; //图类型 有向图,无向图,有向网,无向网
邻接表的存储结构定义:
typedef struct ArcNode{//弧结点
int adjvex;
InfoType *Info; //弧的附加信息
double adj; //邻接数 1或w
struct ArcNode *nextarc;
}ArcNode;
typedef struct VNode{ //图结点
VertexType data;
ArcNode *firstarc; //头结点
}VNode,*AdjList;
//图的邻接表存储结构定义
typedef struct{
AdjList vertices; //邻接表
int vexnum,arcnum; //图结点数,弧数
GraphKind kind; //图类型
}ALGraph;
若G中存在顶点v 返回v的位置 否则返回-1.
int LocateVex(ALGraph &G,VertexType v){
//若G中存在顶点v 返回v的位置 否则返回-1
for(int i=0;i<G.vexnum;i++)
if(G.vertices[i].data==v)
return i;
return -1;
}
图的创建.输入图的种类和边顶点构造图.
Status CreateGraph(ALGraph &G){
//图的创建
//输入图的种类和边顶点构造图
scanf("%d",&G.kind);
switch(G.kind){
case DG: return CreateDG(G);
case DN: return CreateDN(G);
case UDG: return CreateUDG(G);
case UDN: return CreateUDN(G);
default: return ERROR;
}
}
创建有向图G.
Status CreateDG(ALGraph &G){
//创建有向图G
int i,j,k;
VertexType v1,v2;
ArcNode *arc;
scanf("%d %d",&G.vexnum,&G.arcnum);
if(!(G.vertices=(AdjList)malloc(G.vexnum*sizeof(VNode)))) //创建邻接表
exit(OVERFLOW);
for(i=0;i<G.vexnum;i++){
scanf(" %c",&G.vertices[i].data); //输入结点
G.vertices[i].firstarc=NULL;
}
for(k=0;k<G.arcnum;k++){ //输入弧
scanf(" %c %c",&v1,&v2);
i=LocateVex(G,v1);
j=LocateVex(G,v2);
if(!(arc=(ArcNode *)malloc(sizeof(ArcNode))))
exit(OVERFLOW);
arc->adjvex=j;
arc->adj=1.0;
arc->Info=NULL;
arc->nextarc=G.vertices[i].firstarc; //插入到开始位置 邻接点与输入逆序排列
G.vertices[i].firstarc=arc;
}
return OK;
}