图的广度优先遍历与树的宽度优先遍历类似,实现方法也类似。但是相对树,图存在一种特殊情况——环路,环路使得一个已经遍历过的结点,会在其后代结点的子结点中再次被遍历,从而产生多余的读取操作。为了解决这个问题,我们需要为结点设置一个状态以标记其是否已被遍历过。
下面是图和结点及相关定义。
typedef enum VertexColor
{
Vertex_WHITE = 0, // 未被搜索到
Vertex_BLACK = 1, // 子结点都被搜索完毕
Vertex_GRAY = 2 // 子结点正在被搜索
} VertexColor;
typedef struct GNode
{
int number; // 顶点编号
struct GNode *next;
} GNode;
typedef struct Vertex
{
int number;
VertexColor color; // 搜索过程标记搜索状态
struct Vertex *p;
} Vertex;
typedef struct Graph
{
GNode *LinkTable;
Vertex *vertex;
int VertexNum;
} Graph;
上述定义的图用邻接表来表示点和边的关系,每个顶点有编号和颜色两个属性。顶点的p成员变量记录了该顶点的前驱顶点。
下面的代码用队列实现,将同一层的结点放到队列里面,然后每次出队一个结点,展开该结点的下一层孩子结点,并入队,以此类推。