【算法基础】图的存储与遍历
一、图的存储
在我们存储图的时候,主要使用邻接矩阵、邻接表两种方式来存储。通常邻接矩阵存储稠密图(边多),临界矩阵存储稀疏图(边少)。
1.1 邻接矩阵存储
邻接矩阵听起来比较高大上,其实就是用二维数组来表示
表示点
可见邻接矩阵存储非常
根据以上原理,我们上述无向图的存储结果便是:
1.2 邻接表存储
邻接表也一样,听起来非常高大上,其实相当简单。他就是用链表的思想。如下图所示
例如:点
二、图的存储代码实现
如果我们有如下读入数据
5 6
1 2 2
2 3 1
1 3 4
2 5 3
3 5 1
4 2 4
第一行包含整数
接下来
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); // 切记这里的头链表一定要初始化成 -1
std::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] * N
for i in range(m):
a, b, c = map(int, input().split())
add(a, b, c)
# 同理无向图需要 add(b, a, c)
三、图的遍历代码实现
关于图和树的遍历都是用
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] = True
for 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] = True
for 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] = True
i = h[u]
while i != -1:
j = e[i]
dfs(j)
i = ne[i]
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
2023-12-12 【Pytorch基础实战】第一节,BP神经网络