可以用两个数组分别存储数据元素(顶点)、数据元素之间的关系(边或弧度)。
顶点数组不说了,表示弧的数组称为“邻接矩阵”AdjMatrix。
对于有向图:AdjMatrix[i][j]为0表示顶点i和顶点j之间无弧,1为i和j间有弧。
对于无向图:AdjMatrix[i][j]同样是1表示有弧,0无弧。单AdjMatrix[i][j]为1则一定有AdjMatrix[j][i]为1,因为弧是无方向对称的。
对于网(弧带权):AdjMatrix[i][j]上是w或者无穷大,w表示连通且有权值w。无穷大是不连通。
数据结构定义如下:
typedef struct { int vexs[MAX_VNUM]; // 所有顶点 int nvexs; // 顶点数目 int arcs[MAX_VNUM][MAX_VNUM]; // 邻接矩阵(即弧信息) int narcs; // 弧的数量 } Graph;
下面我们用上面的结构完成一个无向连通图的创建和DFS。
#include <stdio.h> #include <string.h> #define MAX_VNUM 100 typedef struct { int vexs[MAX_VNUM]; // 所有顶点 int nvexs; // 顶点数目 int arcs[MAX_VNUM][MAX_VNUM]; // 邻接矩阵(即弧信息) int narcs; // 弧的数量 } Graph; int graph_locate_vec(Graph* graph, int val) { int i; for(i=0; i<graph->nvexs; i++) { if(graph->vexs[i]==val) { return i; } } return -1; } void graph_create_graph(Graph* graph) { int i, j; // 存储顶点 printf("Please enter n for vex(s) :\n"); scanf("%d", &graph->nvexs); for(i=0; i<graph->nvexs; i++) { printf("Please enter a int for vecs(%d) :\n", i); scanf("%d", &graph->vexs[i]); } // 存储弧度 memset(graph->arcs, 0, sizeof(int)*MAX_VNUM*MAX_VNUM); printf("Please enter m for arc(s) :\n"); scanf("%d", &graph->narcs); for(i=0; i<graph->narcs; i++) { int x, y; printf("Please enter v1, v2 for vecs(%d) :\n", i); scanf("%d %d", &x, &y); x = graph_locate_vec(graph, x); y = graph_locate_vec(graph, y); if(x==-1 || y==-1) { i--; printf("Invalid v1 or v2.\n"); continue; } graph->arcs[x][y] = 1; graph->arcs[y][x] = 1; } } int flag[MAX_VNUM]; void graph_dfs_(Graph* graph, int pos) { int i; if(flag[pos]==0) { //Visit flag[pos] = 1; printf("Visit %d\n", graph->vexs[pos]); for(i=0; i<graph->nvexs; i++) { if(graph->arcs[pos][i]==1) { graph_dfs_(graph, i); } } } } void graph_dfs(Graph* graph) { int i; memset(flag, 0, sizeof(int)*MAX_VNUM); for(i=0;i<graph->nvexs;i++) { graph_dfs_(graph, i); } } int main() { Graph g; graph_create_graph(&g); graph_dfs(&g); return 0; }
测试数据:
8 1 2 3 4 5 6 7 8 9 1 2 1 3 2 4 2 5 5 8 4 8 3 6 3 7 6 7
输出结果:
Visit 1 Visit 2 Visit 4 Visit 8 Visit 5 Visit 3 Visit 6 Visit 7