用链式前向星存储图

article/2025/10/16 11:57:40

        图最常用的存储结构主要是邻接矩阵和邻接表。当顶点数太大时,用二维数组表示的邻接矩阵可能超内存(MLE),而用邻接表的编码工作量较大,此时,使用vector数组或链式前向星模拟邻接表是不错的选择。因vector数组容易理解,这里仅介绍链式前向星存储图。

        设有向图的顶点数n=5,边数m=10,输入的边用三个整数from, to, w,分别表示一条边的起点(弧尾顶点)、终点(弧头顶点),边上的权值。输入的10条边如下:

3 4 7
4 1 3
1 3 5
2 4 8
3 2 5
2 3 6
4 2 5
1 2 9
2 1 4
3 5 7

        因链式前向星存储图实际上是静态链表,即用数组模拟链表,这里先回顾邻接表存储图的知识,以便读者能更好地理解链式前向星。若读者清楚知道这部分内容,则可跳过。

        邻接表包含表头结点表(一个数组,设为head)和边表(若干链表)两部分,边表的每个链表结点包含邻接点to,权值weight,指向下一条边的指针域next。每条边采用头插法插入对应链表中,则用上述的数据构建的邻接表如下(表头结点表用整型指针数组即可,1~5表示下标):

         相应的实现代码如下:

//有向图的邻接表实现 
#include <iostream>
using namespace std;
const int N=10;
struct ENode{  int to;   		//某弧所指向顶点的下标int weight;     //弧上的权重ENode* next; 	//指向下一条弧
};
ENode* head[N];
int n, m;void insertArc(int from, int to, int weight) {	// 将弧<from,to>加入图ENode *s=new ENode; s->to=to;s->weight=weight;s->next=head[from]; 				   		// 插到链表head[from]的头部        head[from]=s;
}
void output() {                                 //逐个顶点输出各边 for(int i=1;i<=n;i++) {cout<<i<<"";ENode *p=head[i];		while(p!=NULL) {cout<<"->("<<p->to<<","<<p->weight<<")";p=p->next;}cout<<endl;}
}
int main() {	cin>>n>>m;for(int i=1;i<=n;i++) head[i]=NULL;for(int i=0;i<m;i++){	int from, to, w;	cin>>from>>to>>w;insertArc(from, to, w);}output();return 0;
}

        输入如下:

5 10
3 4 7
4 1 3
1 3 5
2 4 8
3 2 5
2 3 6
4 2 5
1 2 9
2 1 4
3 5 7

        输出结果如下:

1->(2,9)->(3,5)
2->(1,4)->(3,6)->(4,8)
3->(5,7)->(2,5)->(4,7)
4->(2,5)->(1,3)
5

        理解邻接表之后,就可以开始链式前向星了。关键是两个数组,一个是类似邻接表的表头结点表的整数数组head,其中head[i]表示以i为起点的最后(输入)那条边的序号(或称编号),对应邻接表边表中以i为起点的第一条边的编号;另一个是next(实现时next作为表示边的结构体的一个成员,用一个结构体数组表示边集,next是结构体数组元素的一个域),其中next[i]表示以第i条边的起点为起点的前一条(输入)边的编号,对应邻接表边表中的下一条边的编号。设边结构体包含的成员为邻接点to,权值weight,指向下一条边的指针(实际上是一个整数)next,则可得上述数据构建的链式前向星(图中的起点是为方便阅读,可不必存储;有时为方便起见,可在边结构体增加起点成员from)如下:

        相应的实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int N=10, M=100;
struct Edge {int to; 	//一条边的终点(弧头顶点)int weight; //边上的权值int next;	//以该条边的起点(弧尾顶点)为起点的前一条(输入)边的编号,对应邻接表边表中的下一条边的编号
};
int head[N];   //head[i]:以i为起点的最后(输入)那条边的编号;对应邻接表边表中以i为起点的第一条边的编号
Edge edges[M];
int cnt; 	//边的编号计数器
int n,m; 	//实际的顶点数和边数
void output();
void addEdge(int from, int to, int w) {cnt++;						//边数增1edges[cnt].to=to;			//终点直接赋值edges[cnt].weight=w;		//边上的权值直接赋值edges[cnt].next=head[from]; //相当于把第cnt条边链接到第from个顶点的第一条边之前head[from]=cnt; 			//把第from个顶点的head值置为当前以from为起点的最后一条边的编号,相当于把最后一条边作为边表的第一条边 
}
int main() {cin>>n>>m;cnt=0;fill(head+1,head+n+1,-1);//把head[1]~head[n]都置为1for(int i=0; i<m; i++) { //输入m条边,建立链式前向星存储结构int from,to,w;cin>>from>>to>>w;addEdge(from, to, w);}output();				//输出head、edges数组验证return 0;
}
void output() {				//输出head、edges数组的函数cout<<"head:\n";for (int i=1; i<=n; i++) {cout<<i<<": "<<head[i]<<endl;}cout<<"edges:\n";for (int i=1; i<=m; i++) {cout<<i<<": "<<edges[i].to<<" "<<edges[i].weight<<" "<<edges[i].next<<endl;}
}

     

        输入如下:

5 10
3 4 7
4 1 3
1 3 5
2 4 8
3 2 5
2 3 6
4 2 5
1 2 9
2 1 4
3 5 7

        输出结果如下:

head:
1: 8
2: 9
3: 10
4: 7
5: -1
edges:
1: 4 7 -1
2: 1 3 -1
3: 3 5 -1
4: 4 8 -1
5: 2 5 1
6: 3 6 4
7: 2 5 2
8: 2 9 3
9: 1 4 6
10: 5 7 5

        


        每段岁月都有价值。谨以此文纪念2021年暑假集训。祝愿集训队员们都有美好的未来!明天的你会感谢今天奋斗的自己,加油!


http://chatgpt.dhexx.cn/article/uPSc7ovp.shtml

相关文章

链表、链式前向星

讲链表的时候就卡在这里了&#xff0c;最短路又卡在链式前向星上了&#xff0c;毕竟是图论基础&#xff0c;觉得还是有必要写一写防止下次再懵。 链表都是头插法&#xff01;&#xff01;即每次我们给他插一个头。 普通链表 先初始化令head-1,idx-1. void add_tohead(int x…

链式前向星(详细讲述)

在dalao的压迫下本蒟蒻发个博客&#xff0c;给大家讲一下链式前向星&#xff08;新手&#xff0c;写错了轻喷&#xff09; 首先说明一点链式前向星适合于稀疏图&#xff0c;而邻接矩阵则更适合稠密图&#xff0c;所以最好看好数据范围再决策使用哪个方法&#xff0c;当然有些题…

链式前向星与邻接表对比

本文图片及数据 对于这样一张有向图&#xff1a; 输入边的顺序如下&#xff1a; 1 2 2 3 3 4 1 3 4 1 1 5 4 5 对于邻接表来说是这样的&#xff1a; 1 -> 2 -> 3 -> 5 2 -> 3 3 -> 4 4 -> 1 -> 5 5 ->^ 对于链式前向星来说是这样的&…

链式前向星存图(有图详解)

链式前向星:既然是链式那么肯定和链表相关,前向星是每次指向都向前 链式前向星存图是以边为中心,并不是以结点为中心,它记录的是边的一些属性,包括边边的id、头节点、尾结点、权值、边的指向! 边的指向是遍历图的时候需要按照一定顺序去遍历,而不能胡乱的去遍历,那么就需要这些…

链式前向星的详解

目录 1&#xff1a;链式前向星的概念解释 2&#xff1a;代码展现 链式前向星是一种非常好用的有向图存储方式&#xff0c;但是它的代码难度却有点大。作者在这上面花了很长的时间才弄懂。虽然有其他的博客大佬写的很好&#xff0c;但总感觉不太适合小白选手&#xff08;比如说…

链式前向星基本原理

一、概述 我们在学习图论的时候学习了一种图的存储结构--二维数组邻接矩阵储存&#xff0c;他虽然可以表达直观&#xff0c;快速访问连接两点的边&#xff0c;但是它占用空间大&#xff0c;只适用于点少的图&#xff0c;所以我们需要一种能够可以存储大型图的东西--链式前向星…

链式前向星的原理图解

笔者写下这篇文章的契机是&#xff0c;前两天在上机课用纯链式存储写题&#xff0c;累的够呛。于是痛定思痛&#xff0c;在此梳理一遍链式前向星&#xff0c;也希望能给有同样困扰的同学们提供一点帮助。 在进入正题之前&#xff0c;我们先用邻接矩阵和邻接表引入。 邻接矩阵表…

【链式前向星+存图】讲解

大佬的链式前向星:https://blog.csdn.net/acdreamers/article/details/16902023 【前向星】&#xff1a; 解释一下&#xff1a; 【前向星和链式前向星的不同】&#xff1a; 【给出链式前向星的代码实现】&#xff1a; #include<bits/stdc.h> using namespace std; #def…

链式前向星——最完美图解

图的存储方法很多,最常见的除了邻接矩阵、邻接表和边集数组外,还有链式前向星。链式前向星是一种静态链表存储,用边集数组和邻接表相结合,可以快速访问一个顶点的所有邻接点,在算法竞赛中广泛应用。 链式前向星存储包括两种结构: 边集数组:edge[ ],edge[i]表示第i条边…

链式前向星(详解)

链式前向星&#xff08;详解&#xff09; 转自&#xff1a;传送门 我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和…

链式前向星

一 点睛 链式前向星采用了一种静态链表存储方式&#xff0c;将边集数组和邻接表相结合&#xff0c;可以快速访问一个节点的所有邻接点。 链式前向星有如下两种存储结构。 1 边集数组 edge[],edge[i] 表示第 i 条边。 2 头节点数组 head[],head[i] 存储以 i 为起点的第1条边…

深度理解链式前向星

我们首先来看一下什么是前向星. 前向星是一种特殊的边集数组,我们把边集数组中的每一条边按照起点从小到大排序,如果起点相同就按照终点从小到大排序, 并记录下以某个点为起点的所有边在数组中的起始位置和存储长度,那么前向星就构造好了. 用len[i]来记录所有以i为起点的边在数…

链式前向星(超详细)

前向星和链式前向星 链式前向星 添加边的操作 链式前向星&#xff0c;就是以链式结构来储存前向星&#xff0c;每条边就要用结构体&#xff0c;结构体中包含三个数据&#xff1a; Edge[i].to &#xff1a;第i条边的终点 Edge[i].next &#xff1a;与第i条边同一个起点的下…

stm32串口中断的接收

利用串口使得led点亮 利用之前的串口函数加上NVIC的中断函数结构体 定义结构体 定义 配置抢占优先级的组别 配置NVIC串口中断的结构体&#xff1a;中断的通道&#xff0c;配置抢占优先级和子优先级 使能CMD 结构体初始化 还有需要配置中断串口的配置&#xff1a; 串口 接…

STM32串口下载

使用FlyMCU下载程序 1.上电前&#xff0c;设置BOOT01&#xff0c;BOOT10。或者是在上电后&#xff0c;设置BOOT01&#xff0c;BOOT10之后&#xff0c;然后按一下复位按键&#xff0c;从而通过串口下载程序。 2.&#xff0c;在MDK编译加载生成的hex文件&#xff0c;并勾选右边的…

STM32 串口发送乱码问题

STM32 串口发送乱码问题 一、问题状况&#xff1a; 显示为一堆乱码&#xff0c;&#x1f4a2;&#x1f620;&#x1f4a2;晕啊 。 二、解决方法 (通常问题是出在step3:调整外部振荡器默认值) step1:检查时钟树配置 设置晶振为开发板上外部晶振一致的8MHz。 step2:检查波…

STM32串口发送和接收

采用标准库 主控STM32F103C8T6 03代码&#xff1a; #include "main.h" #include "led/led.h" #include "exit/exit.h" #include "uart/uart.h"int main() {NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);InitLED();InitExit();I…

stm32串口控制LED灯

实验要求&#xff1a;电脑串口控制单片机的LED灯 led.c #include "led.h" #include "delay.h" /*初始化led所在口的时钟以及一些输入输出的相关设置*/void Led_Init() {GPIO_InitTypeDef GPIO_Initstructure;RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIO…

stm32串口收发总结

stm32串口的使用过程&#xff1a; 1.使能串口时钟&#xff0c;同时使能串口对应的GPIO的时钟&#xff1b; 2.设置串口引脚的输入输出模式、速率&#xff0c;并初始化GPIO引脚&#xff1b; 3.对于需要接收数据的串口&#xff0c;配置其中断&#xff0c;并使能&#xff1b; 4.设置…

STM32串口发送中断踩坑

今天想测试下Modbus设备&#xff0c;手上暂时没有串口转485的模块&#xff0c;就打算用手上的stm32f042的开发板做个串口转485模块。如下所示 但是软件实际开发过程中&#xff0c;遇到了麻烦。 现象: 在打开串口接收中断时&#xff0c;串口会一直产生除接收中断外的其它中断…