//图的邻接表示
static struct ArcNode {
int adjvex; //该边所指向的节点的位置
struct ArcNode* nextarc; //指向下一条边的指针
int info; //该边的信息
};
static struct VNode {
char data; //顶点信息
ArcNode* firstArc; //指向第一条边的指针
};
static struct AGraph {
vector<VNode> adjList; //邻接表
int n, e; //顶点数和边数
};
//图的深度遍历DFS
vector<bool> visit;
void DFS(AGraph * G, int v)
{
ArcNode* p = NULL;
visit[v] = true;
//Visit(s); //顶点的访问函数
p = G->adjList[v].firstArc;
while (p != NULL)
{
if (!visit[p->adjvex])
{
DFS(G, p->adjvex); //(1)
}
p = p->nextarc; // 指向下一条边
}
}
/*
对比二叉树的前序遍历对比
void Preorder(btNode* p)
{
if(NULL != p)
{
visit(p);
preorder(p->lchild); // (2)
preorder(p->rchild); //(3)
}
}
说明一下:图的DFS类似于二叉树的先序遍历。对比二者,不难发现:二叉树中的(2)和(3)两句为递归访问当前节点的两个分支,
对应与图的DFS代码段中就是while循环内的语句(1),实现了递归地访问当前顶点的多个分支,两者十分相似。区别在于:二叉树
只需要递归地访问当前节点的两个分支,图的深度优先搜索遍历则是要递归地访问多个分支
*/
//图的广度优先遍历
void BFS(AGraph* G, int v, vector<bool>& visit)
{
fill(visit.begin(), visit.end(), false); //清零visit数组
ArcNode* p = NULL;
queue<int> q;
//访问顶点V,注意一定是在节点入队之前设置访问标记,这样才能避免节点重复入队列,类似于树的先序遍历
//如果是在节点出队列的时候设置访问标记,这就很大可能导致节点重复进入队列,降低算法的效率
visit[v] = true;
q.push(v);
while (!q.empty())
{
auto front = q.front(); //这里是节点出队列的地方
q.pop();
p = G->adjList[front].firstArc;
while (p != NULL)
{
if (visit[p->adjvex] == false)
{
//此处加上访问顶点p->adjvex的函数
visit[p->adjvex] = true; //设置新节点的访问标记
q.push(p->adjvex); //该顶点入队
}
p = p->nextarc;
}
}
}