【图论】树、图的存储与遍历

学习资料
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__

  • 本文作者: Tshaxz
  • 本文链接: https://www.cnblogs.com/Tshaxz/p/18711101
  • 关于博主: 评论和私信会在第一时间回复。或者直接私信我。
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
  • 声援博主: 如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。
  • posted @ 2025-02-12 10:42  Tshaxz  阅读(0)  评论(0编辑  收藏  举报
    相关博文:
    阅读排行:
    · DeepSeek-R1本地部署如何选择适合你的版本?看这里
    · 开源的 DeepSeek-R1「GitHub 热点速览」
    · 传国玉玺易主,ai.com竟然跳转到国产AI
    · 揭秘 Sdcb Chats 如何解析 DeepSeek-R1 思维链
    · 自己如何在本地电脑从零搭建DeepSeek!手把手教学,快来看看! (建议收藏)
    Language: HTML
    点击右上角即可分享
    微信分享提示