图的遍历 C++(邻接矩阵/邻接表)

本文详细介绍了图的深度优先搜索(DFS)和广度优先搜索(BFS)的基本思路及伪代码,提供了邻接矩阵和邻接表两种数据结构的实现。DFS通过递归遍历所有未访问的顶点,BFS则利用队列逐层访问。这两种算法在遍历图的连通块时各有优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

DFS

基本思路

就是将经过的顶点设置为已访问,在下次递归遇到这个顶点就无视,直到整个图顶点都被标记已访问。

伪代码思路

DFS(u){//访问顶点u
vis[u] = true;		//设置u点已访问
	for(从u出发能到达的所有顶点v)
		if vis[u] == false	//如果v未被访问
			DFS(v);	//递归访问v
}
DFSTrave(G){	//遍历图G
	for(G的所有顶点) //防止非连通图的情况,有多个连通块
		if vis[u] == false	//如果u未被访问
			DFS(u);				//访问u所在连通块

邻接矩阵版

#include <bits/stdc++.h>
using namespace std;
const int MAXV = 1000;
const int INF = 10000000; //上限值
int n, G[MAXV][MAXV];     //n个顶点,MAXV最大顶点数
bool vis[MAXV] = {false};
void DFS(int u, int depth)
{
	vis[u]=true;
	// 对u的操作可以在这进行
    for (int v = 0; v < n; v++)
    {
        if (vis[u] == false && G[u][v] != INF)
            DFS(v, depth + 1);
    }
}

void DFSTrave() //遍历图G
{
    for (int u = 0; u < n; u++)
    {
        if (vis[u] == false)
            DFS(u, 1); //  访问u和u所在的连通块,1表示初始为第一层
    }
}

邻接表版

#include <bits/stdc++.h>
using namespace std;
const int MAXV = 1000;
const int INF = 10000000; //上限值
vector<int> Adj[MAXV];
int n;
bool vis[MAXV] = {false};

void DFS(int u, int depth)
{
    vis[u] = true;
    // 对u的操作可以在这进行
    for (int i = 0; i < Adj[u].size(); i++)
    {
        int v = Adj[u][i];
        if (vis[v] == false)    //如果未被访问,就访问该点的下一层
            DFS(v, depth + 1);
    }
}

void DFSTrave() //遍历图G
{
    for (int u = 0; u < n; u++)
    {
        if (vis[u] == false)
            DFS(u, 1); //  访问u和u所在的连通块,1表示初始为第一层
    }
}

BFS

基本思路

建立一个队列,并把初始顶点加入队列,此后每次都取出队首顶点进行访问,并把从该点出发可以到达的未加入过队列的(不是未访问)的顶点全加入队列,直到队列为空。

伪代码思路

BFS(u){
	queue q;
	将u入队
	inq[u] =true;
	while(q非空){
		取出q的队首元素进行访问;
		for(从u出发可达的所有顶点v)
			if(inq[v]==false)
				将v入队;
				inq[v]=true;
			}
	}
}
BFSTrave(G){
	for(G的所有顶点u)
		if(inq[u]==false){
			BFS(u);
		}
}

邻接矩阵版

#include <bits/stdc++.h>
using namespace std;
const int MAXV = 1000;
const int INF = 10000000; //上限值
int n,G[MAXV][MAXV];
bool inq[MAXV] = {false};

void BFS(int u)
{
    queue<int> q;
    q.push(u);
    inq[u]=true;
    while (!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int v=0;v<n;v++)
        {
            if(inq[v]==false&&G[u][v]!=INF)
            {
                q.push(v);
                inq[v]=true;
            }
        }
    }
    
}

void BFSTrave() //遍历图G
{
    for (int u = 0; u < n; u++)
    {
        if (inq[u] == false)//如果u未曾加入过队列
            BFS(u); //  访问u和u所在的连通块,1表示初始为第一层
    }
}

邻接表版

#include <bits/stdc++.h>
using namespace std;
const int MAXV = 1000;
const int INF = 10000000; //上限值
vector<int> Adj[MAXV];
int n;
bool inq[MAXV] = {false};

void BFS(int u)
{
    queue<int> q;
    q.push(u);
    inq[u]=true;
    while(!q.empty())
    {
        int u=q.front();
        q.pop();
        for(int i=0;i<Adj[u].size();i++)
        {
            int v=Adj[u][i];
            if(inq[v]==false)
            {
                q.push(v);
                inq[v]=true;
            }
        }
    }
}

void DFSTrave() //遍历图G
{
    for (int u = 0; u < n; u++)
    {
        if (inq[u] == false)
        {
            BFS(u); //  访问u和u所在的连通块,1表示初始为第一层
        }
    }
}

若要输出连通块所有其他顶点层号

#include <bits/stdc++.h>
using namespace std;
struct Node
{
    int v;//顶点编号
    int layer;//顶点层号
};

const int MAXV = 1000;
const int INF = 10000000; //上限值
vector<Node> Adj[MAXV];
int n;
bool inq[MAXV] = {false};

void BFS(int s)
{
    queue<Node> q;
    Node start;
    start.v=s;
    start.layer=0;
    q.push(start);
    inq[start.v]=true;
    while(!q.empty())
    {
        Node topNode=q.front();
        q.pop();
        int u=topNode.v;
        for(int i=0;i<Adj[u].size();i++)
        {
            Node next=Adj[u][i];
            next.layer=topNode.layer+1;
            if(inq[next.v]==false)
            {
                q.push(next);
                inq[next.v]=true;
            }
        }
    }
}

void DFSTrave() //遍历图G
{
    for (int u = 0; u < n; u++)
    {
        if (inq[u] == false)
        {
            BFS(u); //  访问u和u所在的连通块,1表示初始为第一层
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值