图表示是一种多对多的关系的数据结构。因为线性表表示的是一种一对一的关系的数据结构,树表示的是一种一对多的数据结构,所以图把线性表和树都包含在内。图由一个非空的有限顶点集合和一个有限边集合组成。当我们描述图的时候,一定要包含以下两个元素:
1、Vertex
2、Edge
ijEdgeijVertexijji
< ij >EdgeijVertexijji
初始化一个图是,可以一条边也没有,但是不能一个顶点也没有。
那么怎么用代码表示一个图?
第一种方法是邻接矩阵表示法:即用矩阵,一个二维数组来表示一个图。
#include <stdio.h> #include <stdlib.h> #define MaxVertex 100 /*最大顶点数*/ #define INFINITY 65535 /*双字节无符号整数的最大值*/ typedef int Vertex; /*二维数组的下标表示顶点,为整型*/ typedef int WeightType; /*边的权值的类型*/ typedef char DataType; /*顶点存储的数据类型为字符型*/ /*图的数据结构*/ typedef struct GraphNode *PtrlGraphNode; struct GraphNode { int numv; /*顶点数*/ int nume; /*边数*/ WeightType wt[MaxVertex][MaxVertex]; /*邻接矩阵*/ DataType Data[MaxVertex]; /*存放顶点的数据*/ /*很多情况下,顶点无数据,此时Data[]可以不用*/ }; typedef PtrlGraphNode Graph;/*用邻接矩阵存储的图*/
用一个二维数组来表示图中一组顶点对的关系,还有一个一维数组来存放顶点的数据。
/*边的数据结构*/ typedef struct EdgeNode *PtrlEdgeNode; struct EdgeNode { Vertex V1, V2; /*有向边<V1, V2>*//*无向边(V1, V2)*/ WeightType weight; /*权重*/ }; typedef PtrlEdgeNode Edge;
边的数据结构,一条边由一组顶点对和权重表示(即顶点对的关系)。
,
/*建立一个有VertexNum个顶点但没有边的空图*/ Graph CreatGraph(int VertexNum) { Vertex i,j; Graph MyGraph; MyGraph=(Graph)malloc(sizeof(struct GraphNode));/*申请空间建立图*/ MyGraph->numv=VertexNum; MyGraph->nume=0; //初始化边数为0; /*对二维数组矩阵初始化*/ for (i=0;i<MyGraph->numv;i++) { for (j=0;j<MyGraph->numv;j++) { MyGraph->wt[i][j]=INFINITY; } } return MyGraph; }
CreatGraphVertexnum0
/*插入边*/ void InsertEdge(Graph MyGraph, Edge MyEdge) { /*插入边<V1, V2>*/ MyGraph->wt[MyEdge->V1][MyEdge->V2]=MyEdge->weight; /*如果是无向图,还要加上插入边<V2, V1>*/ MyGraph->wt[MyEdge->V2][MyEdge->V1]=MyEdge->weight; }
V1V2
Graph BuildGraph() { Graph MyGraph; /*建图*/ Edge MyEdge; /*建边*/ Vertex v; int VertexNum,i; printf("请输入顶点个数"); scanf("%d", &VertexNum); MyGraph=CreatGraph(VertexNum);/*建立一个有numv个顶点,没有边的图*/ printf("请输入边数:"); scanf("%d", &MyGraph->nume); /* 读入边数 */ MyEdge=(Edge)malloc(sizeof(struct EdgeNode));/*建立边结点*/ /*插入边:格式为:"起点->终点->权重"。插入到邻接矩阵*/ for (i=0;i<MyGraph->nume;i++) { scanf("%d %d %d",&MyEdge->V1, &MyEdge->V2, &MyEdge->weight); InsertEdge(MyGraph, MyEdge); } /*如果顶点有数据,就读入数据*/ for (i=0;i<MyGraph->numv;i++) { scanf("%c", &MyGraph->Data[i]); } return MyGraph; }
Graph[ n ][ n ]n0n-1< ij >GraphGraph[ i ][ j ]=10
用邻接矩阵表示法表示出来的矩阵图,有以下特点:
1、0Graph[ n ][ n ]0
2、1221Graph[ 1 ][ 2 ]Graph[ 2 ][ 1 ]1
0110
那么如何解决邻接矩阵浪费空间和时间的问题?我们知道线性表,线性表顺序存储需要实现分配好内存,这样有可能造成空间浪费或空间不够用,于是就有了链表的方法,同样图的表示方法也可以用链表的方式,就是邻接表表示法。
邻接表表示法,即用一个链表的集合,一个一维指针数组,依然用数组下标表示顶点。所以数组的大小就是图中顶点的个数。
#include <stdio.h> #include <stdlib.h> #define MaxVertex 100 /*最大顶点数*/ typedef int Vertex; /*顶点的下标表示顶点*/ typedef int WeightType; /*边的权值类型为整型*/ typedef char DataType; /*顶点存储的数据的类型*/ /*边的数据结构*/ typedef struct EdgeNode *PtrlEdgeNode; struct EdgeNode { Vertex V1, V2; /* 向边<V1, V2>*/ WeightType weight; /*权重*/ }; typedef PtrlEdgeNode Edge; /*邻接点的数据结构*/ typedef struct PointNode *PtrlPointNode; struct PointNode { Vertex index; /*邻接点的下标*/ WeightType weight; /*边的权重*/ PtrlPointNode Next; /*指向下一个邻接点的指针*/ }; /*顶点表头结点的数据结构*/ typedef struct HeadNode { PtrlPointNode HeadEdge; /*边的表头结点指针*/ DataType Data; /*顶点的数据*/ } PointList[MaxVertex]; /*邻接表类型*/ /*图结点的数据结构*/ typedef struct GraphNode *PtrlGraphNode; struct GraphNode { int numv; /*顶点数*/ int nume; /*边数*/ PointList PL; /*邻接表*/ }; typedef PtrlGraphNode ListGraphNode; /*邻接表方式存储图*/
26291822
/*创建一个有Vertexnum个顶点但没有边的图*/ ListGraphNode CreatGraph(int Vertexnum) { Vertex i; ListGraphNode MyGraph; MyGraph=(ListGraphNode)malloc(sizeof(struct GraphNode)); MyGraph->nume=0; MyGraph->numv=Vertexnum; for (i=0;i<MyGraph->numv;i++) { MyGraph->PL[i].HeadEdge=NULL; //初始化数组里各个头结点 } return MyGraph; } /*插入边*/ void InsertEdge(ListGraphNode MyGraph, Edge E) { PtrlPointNode Node; /*邻接点*/ /*插入边<V1, V2>*/ /*为 V2建立新的邻接点*/ Node=(PtrlPointNode)malloc(sizeof(struct PointNode)); Node->index=E->V2; /*将V2插入V1的表头*/ Node->weight=E->weight; Node->Next=MyGraph->PL[E->V1].HeadEdge; MyGraph->PL[E->V1].HeadEdge=Node; /*如果是无向图,还要插入边<V2, V1>*/ Node=(PtrlPointNode)malloc(sizeof(struct PointNode)); Node->index=E->V1; /*将V2插入V1的表头*/ Node->weight=E->weight; Node->Next=MyGraph->PL[E->V2].HeadEdge; MyGraph->PL[E->V2].HeadEdge=Node; } /*创建图*/ ListGraphNode BuildGraph() { ListGraphNode MyGraph; Edge E; Vertex i,j,numv; printf("请输入要读入的顶点个数:"); scanf("%d", &numv); MyGraph=CreatGraph(numv); printf("请输入要读入的边数:"); scanf("%d", &MyGraph->nume); if (MyGraph->nume!=0) { E=(Edge)malloc(sizeof(struct EdgeNode)); /*建立边结点*/ /*读入边:格式为"起点 终点 权重"*/ for (i=0;i<MyGraph->numv;i++) { scanf("%d %d %d", &E->V1, &E->V2, &E->weight); /*插入边到图里*/ InsertEdge(MyGraph, E); } } /*如果顶点有数据的话,读入数据*/ for (i=0;i<MyGraph->numv;i++) { scanf("%c", &MyGraph->PL[i].Data); } return MyGraph; }
< 5, 9 >5995
文章来源: 图的邻接矩阵表示法&邻接表表示法