链式前向星

这篇具有很好参考价值的文章主要介绍了链式前向星。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

链式前向星

学习前建议学习的前置条件

结构体:
vector邻接表:
链表:

概念

链式前向星与邻接矩阵和邻接表一样, 也是主流的一种存图方式.
它的整体结构很像邻接表, 但是邻接表是线性结构, 链式前向星是链式结构, 实现方式不同, 但是思想是一致的
其实就是链式邻接表, 然后起了一个霸气的名字叫"链式前向星"

为什么使用链式前向星?

链式前向星能做到什么?
答: 链式前向星用途和邻接表相一致.
那么既然他们一样, 我们为什么还要学链式前向星?
我们最先接触到的邻接表写法一般都是vector写法 (可以说这个是最便捷的邻接表, 也最容易理解)
vector 用着一时爽, 但是一旦出现这样的画面时, 是不是开始无从下手了!

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++
链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

内存: vector 是 c++STL 中的 动态连续存储线性表, vector在每次扩充容量时默认都会多申请2倍的空间
时间: STL的调用, 内部实现都导致 vector 是一个非常慢的结构

为了避免手写邻接表这样复杂的操作, 又可以得到一个相对较快, 内存占用较低的方式, 因此我们选择链式前向星


链式前向星存图

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

对于上面这个无向图, 我们如何通过链式前向星进行存图呢?

这里提供输入格式:每行输入三个值{u, v, w},代表点u连接点v边权(边长)为w

 1 2 5
 4 1 3
 2 4 12
 3 4 9
 2 3 8

模板

以下是链式前向星的一个模板, 下面我们进行逐层分析

#include<bits/stdc++.h>
using namespace std;
const int MAXN = 100000;
// 创建边结构
struct Edge{
	int v, w, next;
	// 下一个点,边权,当前边的上一个边
}edge[MAXN*MAXN];
int tot, head[MAXN];


// 建边
void AddEdge(int u, int v, int w) {
    // 建边
	edge[tot].v = v;
	edge[tot].w = w;
    // 连边
	edge[tot].next = head[u];
	head[u] = tot++;
}

int main() {
	// 初始化head
	memset(head, -1, sizeof(head));

	// 建边
	int t; cin >> t;
	for (int i = 0; i < t; i++) {
		int u, v, w;
		cin >> u >> v >> w;
		AddEdge(u, v, w);
	}

	// 遍历 u 连接的所有边
	int u; cin >> u;
	for (int i = head[u]; i != -1; i = edge[i].next) {
		cout << edge[i].v << " " << edge[i].w << endl;
	}
}

一、基本结构

学习链式前向星, 我们首先要了解链式前向星的基本结构

边:

const int MAXN = 10000;		// MAXN 表示点的个数
struct Edge{
	int v, w, next;
}edge[MAXN*MAXN];			// 每个节点最多有n-1条边
int tot;
int head[MAXN];				// 头节点数组(存边的下标)

设定Edge结构体表示边的结构
其中 v 代表连接的点(编号), w 代表边的权值, next 代表下一条临接边(边的下标), 而edge数组的下标就代表着边的起点
我们可以与 vector邻接表来对比

// 边结构
struct Edge {
	int v, w;
};
vector<Edge>mp[MAXN];
int main() {
	int u, v, w;
    // 存图
	while (cin >> u >> v >> w) {
        // 无向图, 所以跑两遍
		mp[u].push_back({ v, w });
		mp[v].push_back({ u, w });
	}
	return 0;
}

对比表格

含义\结构 vector邻接表 链式前向星
单边的起点 mp数组的下标 head的下标
单边的终点 Edge中的v Edge中的v
边权 Edge中的w Edge中的w
下一条边下标 不需要(直接线性遍历mp[u]) Edge中的next
起点连接的第一(最后)个边的edge下标 head的值

二、建边

// 建边
void AddEdge(int u, int v, int w) {
    // 建边
	edge[tot].v = v;
	edge[tot].w = w;
    // 连边
	edge[tot].next = head[u];
	head[u] = tot++;
}

链式前向星建边过程展示:

初始化状态:

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

目标1: 创建一条 1 连 2 长度为 5 的边

  1. 建边

    v = 2(接入点), w = 5(权值), 初始状态没有下一条边, 设为-1

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

  1. 连边

    head[u] 指向这条边

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

-----------------------------------------------------------就此第一条边建成----------------------------------------------------------------------

目标2: 在上一条边的基础上, 创建1连4长度为3的边

发现这两条边都是由点1发起的

我们初步设想是这样的效果:

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

但是很显然这样是行不通的! head[1] 只能存储一个int值, 此时却出现了两个, 怎么办!

此时我们可以将这条边和邻接边连接起来.

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

  1. edge[3].next = head[1]; 将edge[3]连接edge[1];
  2. head[1] = 3; head[1]与edge[1]断开并重新与edge[3]建立连接

最终得到这样的效果

链式前向星,# C++,算法竞赛,# 算法模板,算法,数据结构,链表,c++

以此类推, 我们便可以完成所有边的连接

三、遍历边

	// 遍历 u 连接的所有边
	int u; cin >> u;
	for (int i = head[u]; ~i; i = edge[i].next) {
		cout << edge[i].v << " " << edge[i].w << endl;
	}

i 代表着 点u连接的每一条边的下标, 向链表一样, i 通过找到边中的next找到连着的下一条边, 直到找到 -1, 说明找完了文章来源地址https://www.toymoban.com/news/detail-613744.html

	// 遍历 u 连接的所有边
	int u; cin >> u;
	for (int i = head[u]; ~i; i = edge[i].next) {
		cout << edge[i].v << " " << edge[i].w << endl;
	}

i 代表着 点u连接的每一条边的下标, 向链表一样, i 通过找到边中的next找到连着的下一条边, 直到找到 -1, 说明找完了

到了这里,关于链式前向星的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 图的存储--邻接矩阵/边集数组/邻接表/链式邻接表/链式前向星

    使用二维数组w[u][v]存储点u到点v的边的权值。 一般应用在点数不多的稠密图 时间复杂度:O(n 2 ) 空间复杂度:O(n 2 ) 边集数组e[i]存储第i条边的「起点、终点、边权」。在kruskal算法中,将边按边权排序,直接存边。 时间复杂度:O(nm) 空间复杂度:O(m) 出边数组e[u][i]存储u的所

    2024年02月02日
    浏览(38)
  • 【图论】图的存储--链式前向星存图法以及深度优先遍历图

    无向图 - 就是一种特殊的有向图 - 只用考虑有向图的存储即可 邻接矩阵 邻接表 邻接表 存储结构: (为每一个点开了一个单链表,存储这个点可以到达哪个点) 1 : 3-4-null 2 : 1-4-null 3 : 4-null 4 : null 插入一条新的边 比如要插一条边: 2-3 先找到 2 对应的 单链表 然后将 3 插入到单链表

    2024年04月14日
    浏览(46)
  • 【图论C++】树的重心——教父POJ 3107(链式前向星的使用)

    UpData Log👆 2023.9.26 更新进行中 Statement0🥇 一起进步 Statement1💯 有些描述是个人理解,可能不够标准,但能达其意 树 是 图 的一种 特例 , 树 就是 “没有环” 的 连通图 判断一个 图 是否是一个 树 ,需要满足的条件: 1)树根 :一棵树可以基于 无向图 与 有向图 ,区别在

    2024年02月07日
    浏览(43)
  • 数据结构与算法—二叉树数组表示(ArrayBinTree)、二叉树的链式表示(LinkedBinTree)的基于C++模板代码实现

    1、二叉树的顺序表示:ArrayBinTree.h 二叉树的顺序表示法操作方便,但缺点是容易造成存储空间浪费。 这是一个用数组实现的二叉树类模板。它可以创建一个空树,也可以在指定的位置插入结点并设置结点的值,可以删除子树,并支持逐层遍历。使用该类时,需要提供一个元

    2024年02月06日
    浏览(44)
  • 【数据结构和算法】--- 二叉树(3)--二叉树链式结构的实现(1)

    在学习二叉树的基本操作前,需先要创建一棵二叉树,然后才能学习其相关的基本操作。由于现在大家对二叉树结构掌握还不够深入,且为了方便后面的介绍,此处手动快速创建一棵简单的二叉树,快速进入二叉树操作学习,等二叉树结构了解的差不多时,我们反过头再来研

    2024年01月25日
    浏览(63)
  • 算法竞赛:初级算法(第一章:基础数据结构)

    动态链表 动态链表需要 临时分配链表节点 ,使用完毕后释放。 优点 :能及时释放空间,不使用多余内存 缺点 :需要管理空间,容易出错(竞赛一般不用动态链表) 静态链表 静态链表使用 预先分配的一段连续空间 存储链表,这种链表在逻辑上是成立的。 有两种做法:

    2024年01月19日
    浏览(49)
  • 青岛大学_王卓老师【数据结构与算法】Week03_11_线性表的链式表示和实现11_学习笔记

    本文是个人学习笔记,素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享,另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权,请留言作删文处理。 课程视频链接: 数据结构与算法基础–第3周11–2.5线性表的链式表示和实现

    2024年02月12日
    浏览(40)
  • 算法竞赛备赛之经典数据结构训练提升,暑期集训营培训

    我们将结构体和指针结合来实现链表 我们算法主要是用数组来模拟链表,这样效率会高一些。 数组模拟单链表 邻接表:存储图和树 实现一个单链表,链表初始为空,支持三种操作: 向链表头插入一个数 删除第k个插入的数后面的数 在第k个前面插入一个数 数组模拟双链表的

    2024年02月16日
    浏览(54)
  • 【数据结构与算法分析】使用C语言实现队列的两种(带头结点与不带头结点)链式存储,并且给出一种循环队列的设计思想

      当我们编写程序时,经常需要处理各种数据结构。队列是一种常见的数据结构,它有着广泛的应用场景。队列的基本操作包括入队和出队,应用于模拟等待队列、消息队列、计算机缓存等场合。   在实际编程中,我们可以用不同的数据结构来实现队列。本文主要介绍了

    2024年02月08日
    浏览(118)
  • 算法竞赛常用模板库

    本文使用 CC BY-NC-SA 4.0 许可 。 本文包含了笔者常用的 OI 算法、数据结构的模板。 不保证算法最优 ,但能通过相应的模板题(如果有会挂出)。 如有错误请在评论区指出(虽然大抵没人看就是了)。 码风是笔者的 个人习惯 (能看懂就好喵)。 代码会省略快读 Read() 。 持续

    2024年04月08日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包