先用邻接表法定义了一个图
//图的邻接表法
typedef struct ARCNode {
//边表,存放顶点相邻的边弧信息
int adjvex; //该弧指向的顶点位置
struct ARCNode *next; //下一条弧的指针
} ARCNode;
typedef struct VNode {
//顶点表,存放各个顶点
ElemType data; //顶点信息
ARCNode *first; //指针指向该顶点的第一条弧
} VNode, AdjList[MaxNum];
typedef struct {
AdjList point; //邻接表
int vexnum, arcnum; //图的顶点数与弧数
} Graph;
•广度优先BFS
先是需要用到的一些辅助函数
bool visited[MaxNum]; //访问标记数组。判断当前结点是否访问过
void visit(int v) {
//对结点v进行访问
}
int FirstNeighbor(Graph G, int v) {
//求图G中顶点v的第一个邻接点
}
int NextNeighbor(Graph G, int v, int j) {
//在图G中,顶点j为顶点v的一个邻接点
//找到顶点v的邻接点中排在顶点j之后的邻接点
//如果顶点j是最后一个邻接点,返回-1
}
一次BFS只能遍历一个连通分量,定义一个前提函数加上循环,就能够遍历图里所有的连通分量了
void BFSTra(Graph G) {
for (int i = 0; i < G.vexnum; i++) {
visited[i] = false; //访问标记数组初始化为false
}
InitQueue(Q); //初始化队列
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
BFS(G, i); //对图的每个连通分量进行一次BFS
}
}
}
最后是利用队列进行的广度优先BFS
队列相关操作见 《队列的相关操作》
//BFS广度优先
void BFS(Graph G, int v) {
//从顶点v出发遍历图G
visit(v); //访问结点v
visited[v] = true; //标记已访问
EnQueue(Q, v); //已访问结点入队
while (!isEmpty(Q)) {
//队列非空,则循环进行访问
DeQueue(Q, v); //队头的结点v出队
//检查并访问出队结点的所有邻接点
for (int j = FirstNeighbor(G, v); j >= 0; j = NextNeighbor(G, v, j)){
if(!visited[j]){
//邻接点j未被访问
visit(j);
visited[j] = true;
EnQueue(Q,j); //已访问结点入队
}
}
//队列空时,所有结点访问完成
}
}
•代码汇总
#include <stdio.h>
#include <stdbool.h>
#define ElemType int
#define MaxNum 10
#define MaxSize 10
//图的邻接表法
typedef struct ARCNode {
//边表,存放顶点相邻的边弧信息
int adjvex; //该弧指向的顶点位置
struct ARCNode *next; //下一条弧的指针
} ARCNode;
typedef struct VNode {
//顶点表,存放各个顶点
ElemType data; //顶点信息
ARCNode *first; //指针指向该顶点的第一条弧
} VNode, AdjList[MaxNum];
typedef struct {
AdjList point; //邻接表
int vexnum, arcnum; //图的顶点数与弧数
} Graph;
//----------------------------------------------------------------------------------
bool visited[MaxNum]; //访问标记数组。判断当前结点是否访问过
void visit(int v) {
//对结点v进行访问
}
int FirstNeighbor(Graph G, int v) {
//求图G中顶点v的第一个邻接点
}
int NextNeighbor(Graph G, int v, int j) {
//在图G中,顶点j为顶点v的一个邻接点
//找到顶点v的邻接点中排在顶点j之后的邻接点
//如果顶点j是最后一个邻接点,返回-1
}
//BFS广度优先
void BFS(Graph G, int v) {
//从顶点v出发遍历图G
visit(v); //访问结点v
visited[v] = true; //标记已访问
EnQueue(Q, v); //已访问结点入队
while (!isEmpty(Q)) {
//队列非空,则循环进行访问
DeQueue(Q, v); //队头的结点v出队
//检查并访问出队结点的所有邻接点
for (int j = FirstNeighbor(G, v); j >= 0; j = NextNeighbor(G, v, j)){
if(!visited[j]){
//邻接点j未被访问
visit(j);
visited[j] = true;
EnQueue(Q,j); //已访问结点入队
}
}
//队列空时,所有结点访问完成
}
}
void BFSTra(Graph G) {
for (int i = 0; i < G.vexnum; i++) {
visited[i] = false; //访问标记数组初始化为false
}
InitQueue(Q); //初始化队列
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
BFS(G, i); //对图的每个连通分量进行一次BFS
}
}
}
//----------------------------------------------------------------------------------
•深度优先DFS
需要用到和广度优先相同的辅助函数
bool visited[MaxNum]; //访问标记数组。判断当前结点是否访问过
void visit(int v) {
//对结点v进行访问
}
int FirstNeighbor(Graph G, int v) {
//求图G中顶点v的第一个邻接点
}
int NextNeighbor(Graph G, int v, int j) {
//在图G中,顶点j为顶点v的一个邻接点
//找到顶点v的邻接点中排在顶点j之后的邻接点
//如果顶点j是最后一个邻接点,返回-1
}
接下来的部分也很简单,同样考虑遍历所有连通分量,以及使用迭代进行深度优先遍历
void DFSTra(Graph G) {
for (int i = 0; i < G.vexnum; i++) {
visited[i] = false; //访问标记数组初始化为false
}
for (int i = 0; i < G.vexnum; i++) {
if (!visited[i]) {
DFS(G, i); //对图的每个连通分量进行一次BFS
}
}
}
//DFS深度优先
void DFS(Graph G, int v) {
//从顶点v出发遍历图G
visit(v); //访问结点v
visited[v] = true; //标记已访问
//检查并访问结点v的所有邻接点
for (int j = FirstNeighbor(G, v); j >= 0; j = NextNeighbor(G, v, j)){
if(!visited(j)){
DFS(G,j); //对其中一个邻接点递归寻找其深度遍历序列
}
}
}