图论虐我千百遍,我待图论如初恋
邻接表法的难点就在于这一大堆的结构体,让人乍一看头大,仔细一看就不想看了,推荐大家拿个小本本,手动写一下各个结构体,然后写下面的代码时候就可以随时对着本子瞅一眼,以免乱套
图说要有边,好,那就得定义一个边的结构体
//边结构
typedef struct ENode
{
Vertex V1,V2;
WeightType Weight;
} ENode,*PtrToENode;
typedef PtrToENode Edge;
图又说,还得有点……那就再定义一个点的结构体,注意,这里定义的点的结构体命名为AdjVNode,可以理解为基本点
//邻接点结构
typedef struct AdjVNode
{
Vertex AdjV; //邻接点下标
WeightType Weight; //边权重
AdjVNode *Next; //指向下一个邻接点的指针
} AdjVNode,*PtrToAdjVNode;
图双说,你看这么多点,这么多边,怎么管理???去给他们选些小队长出来,所以这里就要定义一个表头结点VNode,这个结点没啥特殊的,里面包含两个东西,一个是AdjVNode(就算是小队长,但是本质并没有变啊),另一个是Data用来表示小队长的私人物品(也就是表头顶点的数据)
//顶点表头结点
typedef struct VNode
{
PtrToAdjVNode FirstEdge; //边表头指针
// DataType Data; //存顶点的数据
} VNode,*PtrToVNode, AdjList[MaxVertexNum];
图叒说,去把这些小队长都给我组织起来,所以需要定义一个数组,来管理这些VNode,那么这些VNode就类似于一个链表的头结点
AdjList[MaxVertexNum];
图叕说,我需要知道自己的顶点数和边数~~~
//图结点
typedef struct GNode
{
int Nv; //顶点数
int Ne; //边数
AdjList G; //顶点表
} GNode,*PtrToGNode;
图……好了别说了,够了
C语言完整代码如下,在Insert功能里可以选择是无向图还所有向图,这里默认是有向有权图
#include<stdio.h>
#include<stdlib.h>
#define MaxVertexNum 100 //最大顶点数
typedef int Vertex; //顶点类型
typedef int WeightType; //边的权重
typedef char DataType; //顶点存储数据类型
//边结构
typedef struct ENode
{
Vertex V1,V2;
WeightType Weight;
} ENode,*PtrToENode;
typedef PtrToENode Edge;
//邻接点结构
typedef struct AdjVNode
{
Vertex AdjV; //邻接点下标
WeightType Weight; //边权重
AdjVNode *Next; //指向下一个邻接点的指针
} AdjVNode,*PtrToAdjVNode;
//顶点表头结点
typedef struct VNode
{
PtrToAdjVNode FirstEdge; //边表头指针
// DataType Data; //存顶点的数据
} VNode,*PtrToVNode, AdjList[MaxVertexNum];
//图结点
typedef struct GNode
{
int Nv; //顶点数
int Ne; //边数
AdjList G; //顶点表
} GNode,*PtrToGNode;
typedef PtrToGNode LGraph; //图的结构
LGraph CreateGraph(int VertexNum)
{
Vertex V;
LGraph Graph;
Graph = (PtrToGNode)malloc(sizeof(GNode));
Graph->Nv = VertexNum;
Graph->Ne = 0;
for(V=0; V<Graph->Nv; V++)
{
Graph->G[V].FirstEdge = NULL;
}
return Graph;
}
void InsertEdge(LGraph Graph,Edge E)
{
PtrToAdjVNode NewNode;
//插入边<V1,V2>
NewNode = (PtrToAdjVNode)malloc(sizeof(AdjVNode));
NewNode->AdjV = E->V2;
NewNode->Weight = E->Weight;
NewNode->Next = Graph->G[E->V1].FirstEdge;
Graph->G[E->V1].FirstEdge = NewNode;
//如果是无向图,那么还需要插入<V2,V1>边
// NewNode = (PtrToAdjVNode)malloc(sizeof(AdjVNode));
// NewNode->AdjV = E->V1;
// NewNode->Weight = E->Weight;
// NewNode->Next = Graph->G[E->V2].FirstEdge;
// Graph->G[E->V2].FirstEdge = NewNode;
}
LGraph BuildGraph()
{
LGraph Graph;
Edge E;
Vertex V;
int Nv;
printf("Please input the number of Vertex\n");
scanf("%d",&Nv);
Graph = CreateGraph(Nv);
printf("Please input the number of Edge\n");
scanf("%d",&(Graph->Ne));
if(Graph->Ne!=0)
{
E = (PtrToENode)malloc(sizeof(ENode));
//输入边的相关信息,“V1 V2 Weight”
for(int i=0; i<Graph->Ne; i++)
{
printf("Please input V1 V2 Weight : ");
scanf("%d %d %d",&E->V1,&E->V2,&E->Weight);
InsertEdge(Graph,E);
}
}
// for(V=0; V<Graph->Nv; V++)
// {
// scanf(" %c",&(Graph->G[V].Data));
// }
return Graph;
}
void Print(LGraph Graph)
{
for(int i=0; i<Graph->Nv; i++)
{
printf("G[%d]->",i);
PtrToAdjVNode p,q;
p = Graph->G[i].FirstEdge;
while(p!=NULL)
{
printf("%d(%d)->",p->AdjV,p->Weight);
p = p->Next;
}
if(p==NULL)
{
printf("NULL");
}
printf("\n");
}
}
int main()
{
LGraph Graph;
Graph = BuildGraph();
Print(Graph);
Edge E;
E = (PtrToENode)malloc(sizeof(ENode));
return 0;
}
()里面就是边的权重,G[0]->2(9)->1(5)->NULL就表示点0到点1的有变且权重为5,点0到点2有边且权重为9
Please input the number of Vertex
3
Please input the number of Edge
3
Please input V1 V2 Weight : 0 1 5
Please input V1 V2 Weight : 0 2 9
Please input V1 V2 Weight : 1 2 8
G[0]->2(9)->1(5)->NULL
G[1]->2(8)->NULL
G[2]->NULL
Process returned 0 (0x0) execution time : 13.504 s
Press any key to continue.