可以用两个数组分别存储数据元素(顶点)、数据元素之间的关系(边或弧度)。
顶点数组不说了,表示弧的数组称为“邻接矩阵”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