【图论】树、图的存储与遍历
学习资料
1.B02 图的存储
2.图是如何存储的:BFS、DFS
各种存图方式的区别
图片来自上述学习资料
这里主要推荐表格中的后两种存图方法,因为适用于各种图。
只有在需要对一个点的所有出边进行排序的场合下,使用vector
存边排序更方便,其余情况vector存边与链式前向星功能一样。
vector邻接表存图(方便排序)
尤其适用于需要对一个点的所有出边进行排序的场合
模版如下
vector<int> e[N]; //邻接表存图
int st[N];
void add(int a, int b) //添加一条边a->b
{
e[a].push_back(b);
}
DFS遍历
//写法一
void dfs(int u)
{
st[u] = 1;
cout << u << ' ';
for (int i = 0; i < e[u].size(); i++)
{
int j = e[u][i];
if (!st[j])
{
dfs(j);
}
}
}
//写法二
void dfs(int x)
{
st[x] = 1;
cout << x << ' ';
for (int &y : e[x]) //遍历点x所有出边所连的结点,y为结点编号
{
if (st[y]) continue;
dfs(y);
}
}
BFS遍历
//写法一
void bfs(int sx)
{
queue<int> q;
q.push(sx);
st[sx] = 1;
while (q.size())
{
int t = q.front();
q.pop();
cout << t << ' ';
for (int i = 0; i < e[t].size(); i++)
{
int j = e[t][i];
if (!st[j])
{
st[j] = 1;
q.push(j);
}
}
}
}
//写法二
void bfs(int sx)
{
queue<int> q;
q.push(sx);
st[sx] = 1;
while (q.size())
{
int t = q.front();
q.pop();
cout << t << ' ';
for (int &y : e[t]) //遍历点t所有出边所连的结点,y为结点编号
{
if (st[y]) continue;
st[y] = 1;
q.push(y);
}
}
}
例题 P5318 【深基18.例3】查找文献
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
using namespace std;
const int N = 1e5 + 10;
int n, m;
vector<int> e[N];
int st[N];
void add(int a, int b)
{
e[a].push_back(b);
}
void dfs(int u)
{
st[u] = 1;
cout << u << ' ';
for (int i = 0; i < e[u].size(); i++)
{
int j = e[u][i];
if (!st[j])
{
dfs(j);
}
}
}
void bfs(int sx)
{
queue<int> q;
q.push(sx);
st[sx] = 1;
while (q.size())
{
int t = q.front();
q.pop();
cout << t << ' ';
for (int i = 0; i < e[t].size(); i++)
{
int j = e[t][i];
if (!st[j])
{
st[j] = 1;
q.push(j);
}
}
}
}
int main()
{
ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
cin >> n >> m;
while (m--)
{
int a, b;
cin >> a >> b;
add(a, b);
}
for (int i = 1; i <= n; i++) sort(e[i].begin(), e[i].end());
dfs(1);
cout << '\n';
memset(st, 0, sizeof st);
bfs(1);
return 0;
}
链式前向星存图(不能排序)
// 对于每个点k,开一个单链表,存储k所有可以走到的点。h[k]存储这个单链表的头结点
int h[N], e[N], ne[N], idx;
// 添加一条边a->b
void add(int a, int b)
{
e[idx] = b, ne[idx] = h[a], h[a] = idx++;
}
// 初始化
idx = 0;
memset(h, -1, sizeof h);
DFS遍历板子
int dfs(int u)
{
st[u] = true; // st[u] 表示点u已经被遍历过
cout << u << ' ';//输出DFS序列
for (int i = h[u]; i != -1; i = ne[i])
{
int j = e[i];
if (!st[j]) dfs(j);
}
}
BFS遍历板子
void bfs(int sx) //sx为起点编号
{
queue<int> q;
q.push(sx);
st[sx] = 1;
while (q.size())
{
int t = q.front();
q.pop();
cout << t << ' '; //输出BFS序列
for (int i = 0; i < e[t].size(); i++)
{
int j = e[t][i];
if (!st[j])
{
st[j] = 1;
q.push(j);
}
}
}
}
__EOF__
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· DeepSeek-R1本地部署如何选择适合你的版本?看这里
· 开源的 DeepSeek-R1「GitHub 热点速览」
· 传国玉玺易主,ai.com竟然跳转到国产AI
· 揭秘 Sdcb Chats 如何解析 DeepSeek-R1 思维链
· 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)