存储图的两种主要方法
- 邻接矩阵
- 邻接表
用邻接矩阵表示图
上述为无权图,如果是有权图则将1改为权值
以邻接矩阵存储的图结构
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv; //顶点数
int Ne; //边数
WeightType G[MaxVertexNum][MaxVertexNum];
DataType Data[MaxVertexNum];
};
typedef PtrToGNode MGraph; //以邻接矩阵存储的图类型
初始化一个有VertexNum个顶点但是没有边的图
typedef int Vertex;
MGraph CreateGraph(int VertexNum)
{
vertex V,W;
MGraph Graph;
Graph=(MGraph)malloc(sizeof(struct GNode));
Graph->Nv=VertexNum;
Graph->Ne=0;
for(V=0;V<Graph->Nv;V++){
for(W=0;W<Graph->Nv;W++){
Graph->G[V][W]=0;
}
}
return Graph;
}
向MGraph中插入边
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1,V2; //有向边<V1,V2>
WeightType Weight; //权重
};
typedef PtrToENode Edge;
void InsertEdge(MGraph Graph,Edge E)
{
//插入边<V1,V2>
Graph->G[E->V1][E->V2]=E->Weight;
//如果是无向图,还需要插入边<V1,V2>
Graph->G[E->V2][E->V1]=E->Weight;
}
完整的建立一个MGraph
输入格式
Nv Ne
V1 V2 Weight
……
标准版本
MGraph BuildGraph()
{
MGraph Graph;
Edge E;
Vertex V;
int Nv,i;
scanf("%d",&Nv);
Graph=CreateGraph(Nv);
scanf("%d",&(Graph->Ne));
if(Graph->Ne!=0) {
E=(Edge)malloc(sizeof(struct ENode));
for(i=0;i<Graph->Ne;i++){
scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
InsertEdge(Graph,E);
}
}
//如果顶点有数据的话,读入数据
for(V=0;V<Graph->Nv;V++>){
scanf("%d",&(Graph->Data[V]));
}
return Graph;
}
简略版本
在我们做题时,时间不是很充裕,不足以让我们一个一个函数写清楚的情况下
我们可以直接将上述多个函数合并
int G[MAXN][MAXN],Nv,Ne;
void BuildGraph()
{
int i,j,v1,v2,w;
scanf("%d",&Nv);
// CrertGraph
for(i=0;i<Nv;i++){
for(j=0;j<Nv;j++){
G[i][j]=0;
}
}
scanf("%d",&Ne);
for(i=0;i<Ne;i++){
scanf("%d %d %d",&v1,&v2,&w);
//InsertEdge
G[v1][v2]=w;
G[v2][v1]=w;
}
}
用邻接表表示图
- 邻接表:G[N]为指针数组,对应矩阵每行一个链表,只存非0元素
邻接表结构
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv; //顶点数
int Ne; //边数
AdjList G; //邻接表
};
typedef PtrToGNode LGraph; //以邻接表存储的图类型
//邻接表结点数组G[N]
typedef struct Vnode{
PtrToAdjVNode FirstEdge;
DataType Data;
}AdjList[MaxVertexNum];//邻接表G[N]类型--指针数组
//边结点结构
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV; //邻接点的G[N]下标
WeightType Weight; //边权重
PtrToAdjVNode Next;
};
LGraph初始化有顶点没有边
typedef int Vertex;
LGraph CreateGraph(int VertexNum)
{
vertex V,W;
LGraph Graph;
Graph=(LGraph)malloc(sizeof(struct GNode));
Graph->Nv=VertexNum;
Graph->Ne=0;
for(V=0;V<Graph->Nv;V++){
Graph->G[V].FirstEdge=NULL;
}
return Graph;
}
向LGraph中插入边
typedef struct ENode *PtrToENode;
struct ENode{
Vertex V1,V2; //有向边<V1,V2>
WeightType Weight; //权重
};
typedef PtrToENode Edge;
void InsertEdge(LGraph Graph,Edge E)
{
PtrToAdjVnode NewNode;
/* 头插法 插入边<V1,V2> */
//为V2建立新的邻接点
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjNode));
NewNode->AdjV=E->V2;
NewNode->Weight=E->Weight;
//将V2插入V1的表头
NewNode->Next=Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge=NewNode;
//如果是无向图,则需要插入边<V2,V1>
//为V1建立新的邻接点
NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjNode));
NewNode->AdjV=E->V1;
NewNode->Weight=E->Weight;
//将V1插入V2的表头
NewNode->Next=Graph->G[E->V2].FirstEdge;
Graph->G[E->V2].FirstEdge=NewNode;
}
完整建立一个LGraph
完整版本的代码(同邻接矩阵)
LGraph BuildGraph()
{
LGraph Graph;
Edge E;
Vertex V;
int Nv,i;
scanf("%d",&Nv);
Graph=CreateGraph(Nv);
scanf("%d",&(Graph->Ne));
if(Graph->Ne!=0) {
E=(Edge)malloc(sizeof(struct ENode));
for(i=0;i<Graph->Ne;i++){
scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
InsertEdge(Graph,E);
}
}
//如果顶点有数据的话,读入数据
for(V=0;V<Graph->Nv;V++>){
scanf("%d",&(Graph->Data[V]));
}
return Graph;
}