图论复习之链式前向星存图

1|0图论复习之链式前向星存图

1|1理论

其实就是静态建立的邻接表,时间效率为O(n),空间效率也为O(n),遍历效率也为O(n)n是边数。

1|2实现

1|0边的结构

struct Edge { int to, w, next;//终点,边权,同起点的上一条边的编号 }edge[maxn];//边集 int head[maxn];//head[i],表示以i为起点的最后一条边在边集数组的位置(编号)
  • next表示与该边起点相同的上一条边的编号。
  • head[i]数组,表示以i为起点的最后一条边的编号。

1|0边的添加

void add_edge(int u, int v, int w)//加边,u起点,v终点,w边权 { edge[cnt].to = v; //终点 edge[cnt].w = w; //权值 edge[cnt].next = head[u];//以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号 head[u] = cnt++;//更新以u为起点上一条边的编号 }
  • head数组一般初始化为1

1|0边的遍历

遍历寻找以 i 为起点的所有边:

head[i]>>...>1则停止

首先jhead[i]开始,head[i]中存的是以i为起点的最后一条边的编号。

然后通过edge[j].next来找起点相同的上一条边的编号。我们初始化head数组为1,所以找到edge[j].next=1时终止。

for(int i = 1; i <= n; i++)//逐个遍历n个起点 { cout << i << endl; for(int j = head[i]; j != -1; j = edge[j].next)//遍历以i为起点的边 { cout << i << " " << edge[j].to << " " << edge[j].w << endl; } cout << endl; }

具体实例

//Input 5 7 1 2 1 2 3 2 3 4 3 1 3 4 4 1 5 1 5 6 4 5 7

加黑的表示寻找节点1出发的边

  • 对于1 2 1这条边:edge[0].to=2;edge[0].next=1;head[1]=0

  • 对于2 3 2这条边:edge[1].to=3;edge[1].next=1;head[2]=1

  • 对于3 4 3这条边:edge[2].to=4;edge[2],next=1;head[3]=2

  • 对于1 3 4这条边:edge[3].to=3;edge[3].next=0;head[1]=3

  • 对于4 1 5这条边:edge[4].to=1;edge[4].next=1;head[4]=4

  • 对于1 5 6这条边:edge[5].to=5;edge[5].next=3;head[1]=5

  • 对于4 5 7这条边:edge[6].to=5;edge[6].next=4;head[4]=6

1|0整体代码

#include<bits/stdc++.h> using namespace std; const int maxn = 1005;//点数最大值 int n, m, cnt;//n个点,m条边 struct Edge { int to, w, next;//终点,边权,同起点的上一条边的编号 }edge[maxn];//边集 int head[maxn];//head[i],表示以i为起点的第一条边在边集数组的位置(编号) void init()//初始化 { for (int i = 0; i <= n; i++) head[i] = -1; cnt = 0; } void add_edge(int u, int v, int w)//加边,u起点,v终点,w边权 { edge[cnt].to = v; //终点 edge[cnt].w = w; //权值 edge[cnt].next = head[u];//以u为起点上一条边的编号,也就是与这个边起点相同的上一条边的编号 head[u] = cnt++;//更新以u为起点上一条边的编号 } int main() { cin >> n >> m; int u, v, w; init();//初始化 for (int i = 1; i <= m; i++)//输入m条边 { cin >> u >> v >> w; add_edge(u, v, w);//加边 /* 加双向边 add_edge(u, v, w); add_edge(v, u, w); */ } for (int i = 1; i <= n; i++)//n个起点 { cout << i << endl; for (int j = head[i]; j != -1; j = edge[j].next)//遍历以i为起点的边 { cout << i << " " << edge[j].to << " " << edge[j].w << endl; } cout << endl; } return 0; }

__EOF__

本文作者Kdlyh
本文链接https://www.cnblogs.com/kdlyh/p/17827355.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   加固文明幻景  阅读(9)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· Manus爆火,是硬核还是营销?
· 一文读懂知识蒸馏
· 终于写完轮子一部分:tcp代理 了,记录一下
点击右上角即可分享
微信分享提示