一、什么是图

表示“多对多”的关系

包括:

  • 一组顶点:通常用V(Vertex)表示顶点集合
  • 一组边:通常用E(Edge)表示边的集合
    • 边是顶点对:(v, w)∈E,其中v,w∈V
    • 有向边<v, w>表示从v指向w的边(单行线)
    • 不考虑重边和自回路

二、抽象数据类型定义

  • 类型名称:图(Graph)
  • 数据对象集:G(V, E)由一个非空的有限顶点集合v和一个有限边集合E组成。
  • 操作集:对于任意图G ∈ Graph, 以及v ∈ V, e ∈ E
    • Graph Create():建立并返回空图;
    • Graph InsertVertex(Graph G, Vertex v):将v插入G;
    • Graph InsertEdge(Graph G, Edge e):将e插入G;
    • void DFS(Graph G, Vertex v):从顶点v出发深度优先遍历图G;
    • void BFS(Graph G, Vertex v):从顶点v触发宽度优先遍历图G;
    • void ShortestPath(Graph G, Vertex v, int Dist[]):计算图G中顶点v到任一其他顶点的最短距离;
    • void MST(Graph G):计算图G的最小生成树;
    • ......

如何表示图:

不过这种方法,比较浪费时间和空间

 1     /* 图的邻接矩阵表示法 */
 2      
 3     #define MaxVertexNum 100    /* 最大顶点数设为100 */
 4     #define INFINITY 65535        /* ∞设为双字节无符号整数的最大值65535*/
 5     typedef int Vertex;         /* 用顶点下标表示顶点,为整型 */
 6     typedef int WeightType;        /* 边的权值设为整型 */
 7     typedef char DataType;        /* 顶点存储的数据类型设为字符型 */
 8      
 9     /* 边的定义 */
10     typedef struct ENode *PtrToENode;
11     struct ENode{
12         Vertex V1, V2;      /* 有向边<V1, V2> */
13         WeightType Weight;  /* 权重 */
14     };
15     typedef PtrToENode Edge;
16             
17     /* 图结点的定义 */
18     typedef struct GNode *PtrToGNode;
19     struct GNode{
20         int Nv;  /* 顶点数 */
21         int Ne;  /* 边数   */
22         WeightType G[MaxVertexNum][MaxVertexNum]; /* 邻接矩阵 */
23         DataType Data[MaxVertexNum];      /* 存顶点的数据 */
24         /* 注意:很多情况下,顶点无数据,此时Data[]可以不用出现 */
25     };
26     typedef PtrToGNode MGraph; /* 以邻接矩阵存储的图类型 */
27      
28      
29      
30     MGraph CreateGraph( int VertexNum )
31     { /* 初始化一个有VertexNum个顶点但没有边的图 */
32         Vertex V, W;
33         MGraph Graph;
34          
35         Graph = (MGraph)malloc(sizeof(struct GNode)); /* 建立图 */
36         Graph->Nv = VertexNum;
37         Graph->Ne = 0;
38         /* 初始化邻接矩阵 */
39         /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
40         for (V=0; V<Graph->Nv; V++)
41             for (W=0; W<Graph->Nv; W++)  
42                 Graph->G[V][W] = INFINITY;
43                  
44         return Graph; 
45     }
46             
47     void InsertEdge( MGraph Graph, Edge E )
48     {
49          /* 插入边 <V1, V2> */
50          Graph->G[E->V1][E->V2] = E->Weight;    
51          /* 若是无向图,还要插入边<V2, V1> */
52          Graph->G[E->V2][E->V1] = E->Weight;
53     }
54      
55     MGraph BuildGraph()
56     {
57         MGraph Graph;
58         Edge E;
59         Vertex V;
60         int Nv, i;
61          
62         scanf("%d", &Nv);   /* 读入顶点个数 */
63         Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 
64          
65         scanf("%d", &(Graph->Ne));   /* 读入边数 */
66         if ( Graph->Ne != 0 ) { /* 如果有边 */ 
67             E = (Edge)malloc(sizeof(struct ENode)); /* 建立边结点 */ 
68             /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
69             for (i=0; i<Graph->Ne; i++) {
70                 scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 
71                 /* 注意:如果权重不是整型,Weight的读入格式要改 */
72                 InsertEdge( Graph, E );
73             }
74         } 
75      
76         /* 如果顶点有数据的话,读入数据 */
77         for (V=0; V<Graph->Nv; V++) 
78             scanf(" %c", &(Graph->Data[V]));
79      
80         return Graph;
81     }
邻接矩阵

领接表:G[N]为指针数组,对应矩阵每行一个链表,只存非0元素。

  对于网络,结构中要增加权重的域。

  1     /* 图的邻接表表示法 */
  2      
  3     #define MaxVertexNum 100    /* 最大顶点数设为100 */
  4     typedef int Vertex;         /* 用顶点下标表示顶点,为整型 */
  5     typedef int WeightType;        /* 边的权值设为整型 */
  6     typedef char DataType;        /* 顶点存储的数据类型设为字符型 */
  7      
  8     /* 边的定义 */
  9     typedef struct ENode *PtrToENode;
 10     struct ENode{
 11         Vertex V1, V2;      /* 有向边<V1, V2> */
 12         WeightType Weight;  /* 权重 */
 13     };
 14     typedef PtrToENode Edge;
 15      
 16     /* 邻接点的定义 */
 17     typedef struct AdjVNode *PtrToAdjVNode; 
 18     struct AdjVNode{
 19         Vertex AdjV;        /* 邻接点下标 */
 20         WeightType Weight;  /* 边权重 */
 21         PtrToAdjVNode Next;    /* 指向下一个邻接点的指针 */
 22     };
 23      
 24     /* 顶点表头结点的定义 */
 25     typedef struct Vnode{
 26         PtrToAdjVNode FirstEdge;/* 边表头指针 */
 27         DataType Data;            /* 存顶点的数据 */
 28         /* 注意:很多情况下,顶点无数据,此时Data可以不用出现 */
 29     } AdjList[MaxVertexNum];    /* AdjList是邻接表类型 */
 30      
 31     /* 图结点的定义 */
 32     typedef struct GNode *PtrToGNode;
 33     struct GNode{  
 34         int Nv;     /* 顶点数 */
 35         int Ne;     /* 边数   */
 36         AdjList G;  /* 邻接表 */
 37     };
 38     typedef PtrToGNode LGraph; /* 以邻接表方式存储的图类型 */
 39      
 40      
 41      
 42     LGraph CreateGraph( int VertexNum )
 43     { /* 初始化一个有VertexNum个顶点但没有边的图 */
 44         Vertex V;
 45         LGraph Graph;
 46          
 47         Graph = (LGraph)malloc( sizeof(struct GNode) ); /* 建立图 */
 48         Graph->Nv = VertexNum;
 49         Graph->Ne = 0;
 50         /* 初始化邻接表头指针 */
 51         /* 注意:这里默认顶点编号从0开始,到(Graph->Nv - 1) */
 52            for (V=0; V<Graph->Nv; V++)
 53             Graph->G[V].FirstEdge = NULL;
 54                  
 55         return Graph; 
 56     }
 57             
 58     void InsertEdge( LGraph Graph, Edge E )
 59     {
 60         PtrToAdjVNode NewNode;
 61          
 62         /* 插入边 <V1, V2> */
 63         /* 为V2建立新的邻接点 */
 64         NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 65         NewNode->AdjV = E->V2;
 66         NewNode->Weight = E->Weight;
 67         /* 将V2插入V1的表头 */
 68         NewNode->Next = Graph->G[E->V1].FirstEdge;
 69         Graph->G[E->V1].FirstEdge = NewNode;
 70              
 71         /* 若是无向图,还要插入边 <V2, V1> */
 72         /* 为V1建立新的邻接点 */
 73         NewNode = (PtrToAdjVNode)malloc(sizeof(struct AdjVNode));
 74         NewNode->AdjV = E->V1;
 75         NewNode->Weight = E->Weight;
 76         /* 将V1插入V2的表头 */
 77         NewNode->Next = Graph->G[E->V2].FirstEdge;
 78         Graph->G[E->V2].FirstEdge = NewNode;
 79     }
 80      
 81     LGraph BuildGraph()
 82     {
 83         LGraph Graph;
 84         Edge E;
 85         Vertex V;
 86         int Nv, i;
 87          
 88         scanf("%d", &Nv);   /* 读入顶点个数 */
 89         Graph = CreateGraph(Nv); /* 初始化有Nv个顶点但没有边的图 */ 
 90          
 91         scanf("%d", &(Graph->Ne));   /* 读入边数 */
 92         if ( Graph->Ne != 0 ) { /* 如果有边 */ 
 93             E = (Edge)malloc( sizeof(struct ENode) ); /* 建立边结点 */ 
 94             /* 读入边,格式为"起点 终点 权重",插入邻接矩阵 */
 95             for (i=0; i<Graph->Ne; i++) {
 96                 scanf("%d %d %d", &E->V1, &E->V2, &E->Weight); 
 97                 /* 注意:如果权重不是整型,Weight的读入格式要改 */
 98                 InsertEdge( Graph, E );
 99             }
100         } 
101      
102         /* 如果顶点有数据的话,读入数据 */
103         for (V=0; V<Graph->Nv; V++) 
104             scanf(" %c", &(Graph->G[V].Data));
105      
106         return Graph;
107     }
邻接表

猜你喜欢

转载自www.cnblogs.com/ch122633/p/8962365.html