1 /**
2 * C: 邻接矩阵图表示的"无向图(Matrix Undirected Graph)"
3 *
4 */
5
6 #include <stdio.h>
7 #include <stdlib.h>
8 #include <malloc.h>
9 #include <string.h>
10
11 #define MAX 100
12 #define isLetter(a) ((((a)>='a')&&((a)<='z')) || (((a)>='A')&&((a)<='Z')))
13 #define LENGTH(a) (sizeof(a)/sizeof(a[0]))
14
15 // 邻接矩阵
16 typedef struct _graph
17 {
18 char vexs[MAX]; // 顶点集合
19 int vexnum; // 顶点数
20 int edgnum; // 边数
21 int matrix[MAX][MAX]; // 邻接矩阵
22 }Graph, *PGraph;
23
24 /*
25 * 返回ch在matrix矩阵中的位置
26 */
27 static int get_position(Graph g, char ch)
28 {
29 int i;
30 for(i=0; i<g.vexnum; i++)
31 if(g.vexs[i]==ch)
32 return i;
33 return -1;
34 }
35
36 /*
37 * 读取一个输入字符
38 */
39 static char read_char()
40 {
41 char ch;
42
43 do {
44 ch = getchar();
45 } while(!isLetter(ch));
46
47 return ch;
48 }
49
50 /*
51 * 创建图(自己输入)
52 */
53 Graph* create_graph()
54 {
55 char c1, c2;
56 int v, e;
57 int i, p1, p2;
58 Graph* pG;
59
60 // 输入"顶点数"和"边数"
61 printf("input vertex number: ");
62 scanf("%d", &v);
63 printf("input edge number: ");
64 scanf("%d", &e);
65 if ( v < 1 || e < 1 || (e > (v * (v-1))))
66 {
67 printf("input error: invalid parameters!\n");
68 return NULL;
69 }
70
71 if ((pG=(Graph*)malloc(sizeof(Graph))) == NULL )
72 return NULL;
73 memset(pG, 0, sizeof(Graph));
74
75 // 初始化"顶点数"和"边数"
76 pG->vexnum = v;
77 pG->edgnum = e;
78 // 初始化"顶点"
79 for (i = 0; i < pG->vexnum; i++)
80 {
81 printf("vertex(%d): ", i);
82 pG->vexs[i] = read_char();
83 }
84
85 // 初始化"边"
86 for (i = 0; i < pG->edgnum; i++)
87 {
88 // 读取边的起始顶点和结束顶点
89 printf("edge(%d):", i);
90 c1 = read_char();
91 c2 = read_char();
92
93 p1 = get_position(*pG, c1);
94 p2 = get_position(*pG, c2);
95 if (p1==-1 || p2==-1)
96 {
97 printf("input error: invalid edge!\n");
98 free(pG);
99 return NULL;
100 }
101
102 pG->matrix[p1][p2] = 1;
103 pG->matrix[p2][p1] = 1;
104 }
105
106 return pG;
107 }
108
109 /*
110 * 创建图(用已提供的矩阵)
111 */
112 Graph* create_example_graph()
113 {
114 char vexs[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G'};
115 char edges[][2] = {
116 {'A', 'C'},
117 {'A', 'D'},
118 {'A', 'F'},
119 {'B', 'C'},
120 {'C', 'D'},
121 {'E', 'G'},
122 {'F', 'G'}};
123 int vlen = LENGTH(vexs);
124 int elen = LENGTH(edges);
125 int i, p1, p2;
126 Graph* pG;
127
128 // 输入"顶点数"和"边数"
129 if ((pG=(Graph*)malloc(sizeof(Graph))) == NULL )
130 return NULL;
131 memset(pG, 0, sizeof(Graph));
132
133 // 初始化"顶点数"和"边数"
134 pG->vexnum = vlen;
135 pG->edgnum = elen;
136 // 初始化"顶点"
137 for (i = 0; i < pG->vexnum; i++)
138 {
139 pG->vexs[i] = vexs[i];
140 }
141
142 // 初始化"边"
143 for (i = 0; i < pG->edgnum; i++)
144 {
145 // 读取边的起始顶点和结束顶点
146 p1 = get_position(*pG, edges[i][0]);
147 p2 = get_position(*pG, edges[i][1]);
148
149 pG->matrix[p1][p2] = 1;
150 pG->matrix[p2][p1] = 1;
151 }
152
153 return pG;
154 }
155
156 /*
157 * 返回顶点v的第一个邻接顶点的索引,失败则返回-1
158 */
159 static int first_vertex(Graph G, int v)
160 {
161 int i;
162
163 if (v<0 || v>(G.vexnum-1))
164 return -1;
165
166 for (i = 0; i < G.vexnum; i++)
167 if (G.matrix[v][i] == 1)
168 return i;
169
170 return -1;
171 }
172
173 /*
174 * 返回顶点v相对于w的下一个邻接顶点的索引,失败则返回-1
175 */
176 static int next_vertix(Graph G, int v, int w)
177 {
178 int i;
179
180 if (v<0 || v>(G.vexnum-1) || w<0 || w>(G.vexnum-1))
181 return -1;
182
183 for (i = w + 1; i < G.vexnum; i++)
184 if (G.matrix[v][i] == 1)
185 return i;
186
187 return -1;
188 }
189
190 /*
191 * 深度优先搜索遍历图的递归实现
192 */
193 static void DFS(Graph G, int i, int *visited)
194 {
195 int w;
196
197 visited[i] = 1;
198 printf("%c ", G.vexs[i]);
199 // 遍历该顶点的所有邻接顶点。若是没有访问过,那么继续往下走
200 for (w = first_vertex(G, i); w >= 0; w = next_vertix(G, i, w))
201 {
202 if (!visited[w])
203 DFS(G, w, visited);
204 }
205
206 }
207
208 /*
209 * 深度优先搜索遍历图
210 */
211 void DFSTraverse(Graph G)
212 {
213 int i;
214 int visited[MAX]; // 顶点访问标记
215
216 // 初始化所有顶点都没有被访问
217 for (i = 0; i < G.vexnum; i++)
218 visited[i] = 0;
219
220 printf("DFS: ");
221 for (i = 0; i < G.vexnum; i++)
222 {
223 //printf("\n== LOOP(%d)\n", i);
224 if (!visited[i])
225 DFS(G, i, visited);
226 }
227 printf("\n");
228 }
229
230 /*
231 * 广度优先搜索(类似于树的层次遍历)
232 */
233 void BFS(Graph G)
234 {
235 int head = 0;
236 int rear = 0;
237 int queue[MAX]; // 辅组队列
238 int visited[MAX]; // 顶点访问标记
239 int i, j, k;
240
241 for (i = 0; i < G.vexnum; i++)
242 visited[i] = 0;
243
244 printf("BFS: ");
245 for (i = 0; i < G.vexnum; i++)
246 {
247 if (!visited[i])
248 {
249 visited[i] = 1;
250 printf("%c ", G.vexs[i]);
251 queue[rear++] = i; // 入队列
252 }
253 while (head != rear)
254 {
255 j = queue[head++]; // 出队列
256 for (k = first_vertex(G, j); k >= 0; k = next_vertix(G, j, k)) //k是为访问的邻接顶点
257 {
258 if (!visited[k])
259 {
260 visited[k] = 1;
261 printf("%c ", G.vexs[k]);
262 queue[rear++] = k;
263 }
264 }
265 }
266 }
267 printf("\n");
268 }
269
270 /*
271 * 打印矩阵队列图
272 */
273 void print_graph(Graph G)
274 {
275 int i,j;
276
277 printf("Martix Graph:\n");
278 for (i = 0; i < G.vexnum; i++)
279 {
280 for (j = 0; j < G.vexnum; j++)
281 printf("%d ", G.matrix[i][j]);
282 printf("\n");
283 }
284 }
285
286 void main()
287 {
288 Graph* pG;
289
290 // 自定义"图"(输入矩阵队列)
291 //pG = create_graph();
292 // 采用已有的"图"
293 pG = create_example_graph();
294
295 print_graph(*pG); // 打印图
296 DFSTraverse(*pG); // 深度优先遍历
297 BFS(*pG); // 广度优先遍历
298 }