【算法基础】图的存储与遍历

news/2024/12/12 17:00:35/文章来源:https://www.cnblogs.com/wxzcch/p/18602993

一、图的存储

在我们存储图的时候,主要使用邻接矩阵、邻接表两种方式来存储。通常邻接矩阵存储稠密图(边多),临界矩阵存储稀疏图(边少)。

1.1 邻接矩阵存储

邻接矩阵听起来比较高大上,其实就是用二维数组来表示 \(a\) 点与 \(b\) 点之间有一条边。例如在上述无向图中 \(1\)\(4\) 之间有一条无向边。用邻接矩阵来存储的话就是

\[g[1][4] = 19\\ g[4][1] = 19 \]

表示点 \(1\) 到点 \(4\) 之间的权重是 \(19\) ,因为是无向边所以 \(4\) 也可以到 \(9\) 权重是 \(19\) 。如果是有向图,建边的时候仅能根据方向建边

\[g[1][4] = 19 \]

可见邻接矩阵存储非常 \(ez\) 但是由于内存的限制,点也肯定不会太多。如果点很多 \(( 10^4 )\) 就仅能用邻接表存储了。

根据以上原理,我们上述无向图的存储结果便是:

1.2 邻接表存储

邻接表也一样,听起来非常高大上,其实相当简单。他就是用链表的思想。如下图所示

例如:点 \(1\) 可以到达的点有 \(\{2, 3, 4\}\) ,点 \(4\) 可以到达的点有 \(\{1,2,3,5,7,9\}\) 以此不断类推。关于边权,我们也仅需再开一个数组同时来维护即可。

二、图的存储代码实现

如果我们有如下读入数据

5 6
1 2 2
2 3 1
1 3 4
2 5 3
3 5 1
4 2 4

第一行包含整数 \(n\)\(m\)。代表给定一个 \(n\) 个点 \(m\) 条边的有向图

接下来 \(m\) 行每行包含三个整数 \(x,y,z\) ,表示存在一条从点 \(x\) 到点 \(y\) 的有向边,边长为 \(z\)

2.1 邻接矩阵存储实现

const int N = 1010;
int g[N][N];
int main()
{int n, m;std::cin >> n >> m;memset(g, 0x3f, sizeof g);for(int i = 1; i <= m; i++){int x, y, z;std::cin >> x >> y >> z;g[x][y] = z;	// 如果有重边则根据题意保留小边或大边// g[y][x] = z;	// 如果是无向图,点 y 到点 x 也需要建边}
}
N = int(1e3 + 10)
INT_MAX = int(2e10)
g = [[INT_MAX for i in range(N)] for j in range(N)]
n, m = map(int, input().split())
for t in range(m):x, y, z = map(int, input().split())g[x][y] = z 	# 如果有重边则根据题意保留小边或大边# g[y][x] = z;	  如果是无向图,点 y 到点 x 也需要建边

2.2 邻接表利用 vector 实现

int main()
{int n, m;std::cin >> n >> m;std::vector<int> e[n + 1], w[n + 1];	// 注意这里是中括号for(int i = 1; i <= m; i++){int x, y, z;std::cin >> x >> y >> z;e[x].push_back(y);		// 邻接表无法处理重边,直接存就好,后面有最短路的问题,再在后面做处理即可w[x].push_back(z);// 如果是无向图也需要添加, e[y].push_back(x);	w[y].push_back(z);}
}
n, m = map(int, input().split())
e = [[] for i in range(n + 1)]
w = [[] for i in range(n + 1)]  # 或 w = e[:] 这里一定要切片
for i in range(m):x, y, z = map(int, input().split())e[x].append(y)w[x].append(z)# 如果是无向图也需要添加, e[y].append(x);	w[y].append(z);

2.3 邻接表用数组实现(静态的)【链式前向星】

const int N = 1e5 + 10, M = 5e5 + 10;
int h[N], ne[M], e[M], w[M], idx;
int d[N];
int n, m;void add(int a, int b, int c){ne[idx] = h[a], e[idx] = b, w[idx] = c, h[a] = idx++;
}int main()
{memset(h, -1, sizeof h);	// 切记这里的头链表一定要初始化成 -1std::cin >> n >> m;for(int i = 1; i <= m; i++){int a, b, c;std::cin >> a >> b >> c;add(a, b, c); // 同理,如果无向图需要 add(b, a, c);}
}
n, m = map(int, input().split())
INF = 1e12
N = 1000000 + 10
h, e, w, ne = [-1] * N, [0] * N, [0] * N, [0] * N
st = [False] * Nfor i in range(m):a, b, c = map(int, input().split())add(a, b, c)# 同理无向图需要 add(b, a, c)

三、图的遍历代码实现

关于图和树的遍历都是用 \(dfs\)\(bfs\) 进行遍历的。

3.1 邻接矩阵遍历

bool st[N];
void dfs(int u)
{st[u] = true;for(int i = 1; i <= n; i++){if(g[u][i] != 0 && !st[i]) dfs(i);	// 只要点 u 可以达到点 i ,且点 i 没有被访问过,进行遍历即可。// 具体的遍历法制需要根据题意进行修改}
}
st = [False] * (n + 1)
def dfs(u):st[u] = Truefor i in range(1, n + 1):if g[u][i] != 0 and not st[i]: dfs(i)

3.2 邻接表遍历 (vector)

bool st[N];
void dfs(int u)
{st[u] = true;for(int i = 0; i < e[u].size(); i++){if(!st[e[u][i]]) dfs(e[u][i]);  // 只要点 u 可以达到点 i ,且点 i 没有被访问过,进行遍历即可。}
}
st = [False] * (n + 1)
def dfs(u):st[u] = Truefor i in range(len(e[u])):if st[e[u][i]]: dfs(e[u][i])

3.3 邻接表遍历(链式前向星)

bool st[N];
void dfs(int u) {if(st[u]) return;st[u] = true;for (int i = h[u]; i != -1; i = ne[i]){int j = e[i];	// 这个点去哪里dfs(j);}
}
st = [False] * (n + 1)
def dfs(u):st[u] = Truei = h[u]while i != -1:j = e[i]dfs(j)i = ne[i]

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/851461.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决Pandas的to_excel()写入不同Sheet,而不会被重写

一、问题描述 在使用Pandas的to_excel()方法写入数据时,当我们想将多个数据写入一个Excel表的不同DataFrame中,虽然能够指定sheet_name参数,但是会重写整个Excel之后才会存储。 现在有3个sheet,内容如下:>>> import pandas as pd >>> df1 = pd.read_exc…

基于Transformer的生成式人工智能模型的训练和推理以及成员推断攻击的实现

Transformer_AI 2024年11月15日更新 在此教程中,我们将对基于Transformer的生成式人工智能模型及其原理进行一个简单的介绍,并实现其训练和推理过程,且至少支持3种数据集,目前支持数据集有:MNIST、fashionMNIST、CIFAR10等,并给用户提供一个详细的帮助文档。 目录 基本介…

协作文档的核心逻辑:秩序性如何赋能团队?

协作文档:秩序性的数字化创新 在当今高速发展的信息化社会中,协作文档已经成为团队合作和企业运作的重要工具。协作文档不仅提供了便捷的协作环境,更为高效的任务管理和知识共享带来了全新的可能。然而,真正出色的协作文档不只是一个工具,它更是一种体现秩序性的管理理念。…

macOS Sonoma 14.7.2 (23H311) 正式版 ISO、IPSW、PKG 下载

macOS Sonoma 14.7.2 (23H311) 正式版 ISO、IPSW、PKG 下载macOS Sonoma 14.7.2 (23H311) 正式版 ISO、IPSW、PKG 下载 利用小组件进行个性化设置、令人眼前一亮的全新屏幕保护、Safari 浏览器和视频会议的重大更新 请访问原文链接:https://sysin.org/blog/macOS-Sonoma/ 查看…

前端性能优化实战:从加载到渲染的全链路提速

"网站太慢了,用户都在抱怨!"上周,我接手了一个正在运行的电商项目,首屏加载时间竟然长达 8 秒。作为一个对性能有执念的前端开发者,这个数字让我夜不能寐。经过一周的优化,我们把首屏时间压缩到了 2 秒以内。今天,我想和大家分享这个过程中的实战经验。😊 性…

转载:【AI系统】算子手工优化

在上一篇中,探讨了算子计算和调度的概念,并强调了高效调度策略在释放硬件性能和降低延迟方面的重要性。本文,我们将深入讨论手写算子调度时需要考虑的关键因素,并介绍一些著名的高性能算子库。 计算分析 在优化算子前,首先需要知道当前程序的瓶颈在哪里,是计算瓶颈还是访…

强化学习模型的训练和推理以及成员推断攻击的实现

Reinforcement_learning 2024年9月1日更新 在此教程中,我们将对强化学习模型及其原理进行一个简单的介绍,并实现一种强化学习模型的训练和推理过程,且至少支持3种数据集,目前支持数据集有:MNIST、fashionMNIST、CIFAR10等,并给用户提供一个详细的帮助文档。 目录 基本介绍…

ASE8N65S-ASEMI高压N沟道MOS管ASE8N65S

ASE8N65S-ASEMI高压N沟道MOS管ASE8N65S编辑:ll ASE8N65S-ASEMI高压N沟道MOS管ASE8N65S 型号:ASE8N65S 品牌:ASEMI 封装:TO-220F 最大漏源电流:8A 漏源击穿电压:650V 批号:最新 RDS(ON)Max:1.25Ω 引脚数量:3 沟道类型:N沟道MOS管 芯片尺寸:MIL 漏电流: 恢复时间:…

OCR识别智能采集终端-拍照抄表器-数采物联网水电气仪表采集

www.daq-iot.com SC-LP-CAM系列电池供电无线定时拍照摄像头抄表终端水表读表器是一款由数采物联推出的新型数据采集终端,可以用于快速抄表传统老旧机械仪表或无法直接通讯的仪表。它采用摄像直读方式,在设定的时间间隔内进行拍照,并将照片上传到服务器后进行分析识别,得…

testng+allure

1.坐标 <!--Allure报告依赖包--> <dependency> <groupId>io.qameta.allure</groupId> <artifactId>allure-testng</artifactId> <version>${allure.version}</version> <scope>test</scope> </dependency> …

【帆软Report】关于按钮控件的使用

在帆软使用过程中,会遇到一些需求,比如某个功能,某些页面要在特定情况下才可以使用,这篇主要是对按钮在特定情况下显示和隐藏的心得先说需求:有一个打分按钮,要求实现 当传入的状态编码是“1”的时候可以看到并且点击,其他状态编码时按钮无法使用并且隐藏。实现方法如下…