【图的存储】

news/2024/11/27 23:41:39/

更好的阅读体验\color{red}{更好的阅读体验}更好的阅读体验


文章目录

    • 1. 邻接矩阵
    • 2. 边集数组
    • 3. 邻接表
    • 4. 链式邻接表
    • 5. 链式前向星
    • 总结

1. 邻接矩阵


思想

  • 利用二维数组 g[N][N] 存储所有的点到点的权值。
  • 其中 N 为点的数量,g[i][j] 表示点 i 到点 j 的权值。

时间复杂度O(n2)\mathcal{O}(n^2)O(n2)

空间复杂度O(n2)\mathcal{O}(n^2)O(n2)

应用

  • 只在点数不多的稠密图使用。
  • 大部分情况下点的数量 n=103n = 10^3n=103,边的数量 m=106m = 10^6m=106

示例

  • 现有 n 个点共 m 条边,以及每条边的起始点和终点及权值。
  • 这些点和边共同构成一个有向图。
  • 存储这些信息并输出。

在这里插入图片描述

输入

4 5
1 2 20
1 4 40
2 3 50
2 4 60
3 2 30

代码

#include <bits/stdc++.h>
using namespace std;const int N = 1010;  //图的大小int n, m;
int g[N][N];
bool vis[N];  //标记是否走过void dfs(int u){  //深度优先遍历vis[u] = 1;  //标记当前点已经遍历过for(int i = 1; i <= n; i ++){  //遍历n个点if(g[u][i] != 0){cout << u << ' ' << i << ' ' << g[u][i] << endl;if(vis[i]) continue;  //当前的边的终点已经走过则跳过dfs(i);}}
}void solve(){cin >> n >> m;for(int i = 0; i < m; i ++){int a, b, c; cin >> a >> b >> c;g[a][b] = c;// g[b][a] = c;  //如果是无向图加一条边}dfs(1);  //从1号点开始遍历}int main(){solve();return 0;
}

输出

1 2 20
2 3 50
3 2 30
2 4 60
1 4 40

2. 边集数组


思想

  • 利用结构体数组 e[N] 存储边的信息。
  • 其中 e[i] 包含第 i 条边的 {起始点u, 终点v, 边权w}

时间复杂度O(nm)\mathcal{O}(nm)O(nm)

空间复杂度O(m)\mathcal{O}(m)O(m)

应用

  • Kruskal 算法中,需要将边按照边权排序,直接存边。

示例

  • 现有 n 个点共 m 条边,以及每条边的起始点和终点及权值。
  • 这些点和边共同构成一个有向图。
  • 存储这些信息并输出。

在这里插入图片描述

输入

7 6
4 3 90
1 4 30
5 7 80
5 6 60
1 5 20
5 2 70

代码

#include <bits/stdc++.h>
using namespace std;const int N = 1010;  //图的大小int n, m;struct edge{int u, v, w;
}e[N];bool vis[N];  //标记是否走过void dfs(int u){  //深度优先遍历vis[u] = 1;  //标记当前点已经遍历过for(int i = 1; i <= m; i ++){  //遍历m条边if(u == e[i].u){  //找到当前的边的起始点cout << e[i].u << ' ' << e[i].v << ' ' << e[i].w << endl;if(vis[e[i].v]) continue;  //当前的边的终点已经走过则跳过dfs(e[i].v);}}
}void solve(){cin >> n >> m;for(int i = 1; i <= m; i ++){int a, b, c; cin >> a >> b >> c;e[i] = {a, b, c};// e[i] = {b, a, c};  //如果是无向图加一条边}dfs(1);  //从1号点开始遍历}int main(){solve();return 0;
}

输出

1 4 30
4 3 90
1 5 20
5 7 80
5 6 60
5 2 70 

3. 邻接表


思想

  • 利用出边数组 e[N][N] 存储边的信息。
  • 其中 e[u][i] 表示点 u 的所有出边,其出边包含 {终点v, 边权w}

时间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

空间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

应用

  • 可以应用于各种图,但是不能处理反向的边(网络流)。

示例

  • 现有 n 个点共 m 条边,以及每条边的起始点和终点及权值。
  • 这些点和边共同构成一个有向图。
  • 存储这些信息并输出。

在这里插入图片描述

输入

7 6
4 3 90
1 4 30
5 7 80
5 6 60
1 5 20
5 2 70

代码

#include <bits/stdc++.h>
using namespace std;const int N = 1010;  //图的大小int n, m;struct edge{int v, w;
};vector<edge> e;  //边集void dfs(int u, int fa){  //深度优先遍历, fa记录当前点的父节点for(auto p : e[u]){  //遍历所有的出边if(fa == p.v) continue;  //若该出边的终点是父节点,说明已经走过cout << u << ' ' << p.v << ' ' << p.w << endl;dfs(p.v, u);}
}void solve(){cin >> n >> m;for(int i = 1; i <= m; i ++){int a, b, c; cin >> a >> b >> c;e[a].push_back({b, c});// e[b].push_back({a, c});  //如果是无向图加一条边}dfs(1, 0);  //从1号点开始遍历}int main(){solve();return 0;
}

输出

1 4 30
4 3 90
1 5 20
5 7 80
5 6 60
5 2 70 

4. 链式邻接表


思想

  • 利用边集数组 e[N] 存储所有的边的信息,表头数组 h[N][N] 存储点的所有出边的编号。
  • 其中 e[j] 存储第 j 条边的 {起始u, 终点v, 边权w}h[u][i] 存储 u 点的第 i 条边的编号。

时间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

空间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

应用

  • 可以应用于各种图,也能处理反向的边。

示例

  • 现有 n 个点共 m 条边,以及每条边的起始点和终点及权值。
  • 这些点和边共同构成一个无向图。
  • 存储这些信息并输出。

输入

6 5
4 3 90
1 4 30
5 6 60
1 5 20
5 2 70

代码

#include <bits/stdc++.h>
using namespace std;const int N = 1010;  //图的大小int n, m;struct edge{int u, v, w;
};vector<edge> e;  //边集
vector<int> h[N];  //点的所有出边void add(int a, int b, int c){e.push_back({a, b, c});h[a].push_back(e.size() - 1);
}void dfs(int u, int fa){  //深度优先遍历, fa记录当前点的父节点for(int i = 0; i < h[u].size(); i ++){int j = h[u][i];if(fa == e[j].v) continue;cout << u << ' ' << e[j].v << ' ' << e[j].w << endl;dfs(e[j].v, u);}
}void solve(){cin >> n >> m;for(int i = 1; i <= m; i ++){int a, b, c; cin >> a >> b >> c;add(a, b, c);add(b, a, c);  //如果是无向图加一条边}dfs(1, 0);  //从1号点开始遍历}int main(){solve();return 0;
}

输出

1 4 30
4 3 90
1 5 20
5 6 60
5 2 70

5. 链式前向星


思想

  • 一个表头悬挂多个链表。
  • 利用边集数组 e[N] 存储所有的出边的信息,表头数组 h[N] 存储点的第一条出边的编号。
  • 其中 e[i] 存储第 i 条边的 {终点v, 边权w, 下一条边ne}h[u] 存储 u 点的第一条出边的编号。

时间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

空间复杂度O(n+m)\mathcal{O}(n+m)O(n+m)

应用

  • 可以应用于各种图,也能处理反向的边。

示例

  • 现有 n 个点共 m 条边,以及每条边的起始点和终点及权值。
  • 这些点和边共同构成一个无向图。
  • 存储这些信息并输出。

输入

6 5
4 3 90
1 4 30
5 6 60
1 5 20
5 2 70

代码

#include <bits/stdc++.h>
using namespace std;const int N = 1e6 + 3;  //图的大小int n, m;struct edge{int v, w, ne;
}e[N];  //边集int idx, h[N];  //点的第一条出边,idx为下标编号void add(int a, int b, int c){e[idx] = {b, c, h[a]};h[a] = idx ++;
}void dfs(int u, int fa){  //深度优先遍历, fa记录当前点的父节点for(int i = h[u]; ~ i; i = e[i].ne){if(fa == e[i].v) continue;cout << u << ' ' << e[i].v << ' ' << e[i].w << endl;dfs(e[i].v, u);}
}void solve(){cin >> n >> m;memset(h, -1, sizeof h);  //初始化第一条出边为-1for(int i = 1; i <= m; i ++){int a, b, c; cin >> a >> b >> c;add(a, b, c);add(b, a, c);  //如果是无向图加一条边}dfs(1, 0);  //从1号点开始遍历}int main(){solve();return 0;
}

输出

1 5 20
5 2 70
5 6 60
1 4 30
4 3 90

总结


  • 链式邻接表和链式前向星可以解决绝大部分的图论问题。
  • 推荐使用链式前向星,建图方式简便,空间压缩紧密,查找效率高。

http://www.ppmy.cn/news/10951.html

相关文章

外业调查工具助手,照片采集、精准定位、导航、地图查看

你是不是在外业调查时要背着一堆图纸 是不是一不小心图纸污损或丢失&#xff0c;工作又得重做 是不是经常会出现图纸标注的空间不足 是不是外业采集中要携带一大堆繁琐的仪器 是不是每次收集的数据、照片等在整理的过程中发现工作量巨大 是不是经常会出现采集回来的内容跟…

Spring Boot 程序优化的 14 个小妙招!

1.定义配置文件信息2.用RequiredArgsConstructor代替Autowired3.代码模块化4.抛异常而不是返回5.减少不必要的db6.不要返回null7.if else8.减少controller业务代码9.利用好Idea10.阅读源码11.设计模式12.拥抱新知识13.基础问题14.判断元素是否存在1.定义配置文件信息有时候我们…

QT Echarts 联动共享数据表图 使用详解

Echarts是百度的一款可视化界面开发的平台&#xff0c;里面的地图以及数据可视化内容十分丰富&#xff0c;适合用于一些大屏数据显示项目或者一些ui界面开发。每一个ECharts图表使用一个无边框的QWebView来展示&#xff0c;这样多个不同类型的ECharts图表就是多个封装不同类型E…

ubuntu docker elasticsearch kibana安装部署

ubuntu docker elasticsearch 安装部署 所有操作尽量在root下操作. 安装docker 1. 由于是基于宝塔面板安装的所以简答的点击操作即可完成安装. 我这里已经是正常的安装好了. 2.dcoker 镜像加速 https://cr.console.aliyun.com/cn-hangzhou/instances访问这个网址进去进行了…

[数据库迁移]-LVM逻辑卷管理

[数据库迁移]-LVM逻辑卷管理 森格 | 2023年1月 1、本文旨在记录数据库迁移过程&#xff08;下云至机房&#xff09;中&#xff0c;对新磁盘做逻辑卷管理的过程&#xff0c;并对Linux的文件系统和分区做了相关介绍&#xff0c;如有不对之处&#xff0c;敬请指正。 2、对Linux文…

SpringCloud(12)— 分布式事务(Seata)

SpringCloud&#xff08;12&#xff09;— 分布式事务&#xff08;Seata&#xff09; 一 事务基础 1.事务的ACID原则 2.分布式事务问题 在分布式系统下&#xff0c;一个业务跨越多个服务或数据源&#xff0c;每一个服务都是一个事务。 要保证所有分支事务的最终状态一致&am…

React(coderwhy)- 09(项目实战 - 1)

创建React项目 ◼ 创建项目的方式&#xff1a;create-react-app ◼ 项目配置:  配置项目的icon  配置项目的标题  配置jsconfig.json 新建jsconfig.json文件&#xff0c;在文件中粘贴以下内容{"compilerOptions": {"target": "es5","…

unity日记4(鼠标键盘交互、实例)

目录 鼠标事件 鼠标点击、抬起、长按事件 键盘事件 键盘点击、抬起、长按事件 键盘键位替换 实例&#xff1a;鼠标-音乐播放/暂停 实例&#xff1a;调用其他对象的组件&#xff08;双方法&#xff09; 实例&#xff1a;调整其他对象的公有参数 鼠标事件 鼠标点击、抬起、长…