news 2026/3/16 5:01:34

图论_图的存储结构

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
图论_图的存储结构

邻接矩阵

顶点结构

顺序表存顶点集,每个顶点包含数据data,顶点编号id(大部分情况下和顶点在数组中的下标对应)

struct Vertex{ int id; DataType data; };

边结构

用边的两个顶点在顺序表中的索引表示边,由于一条边包含两个索引,所以用一个二维数组来表示E集,边存在就填1,不存在就填0(自己指向自己的边)或INF(不同顶点之间的边)

typedef int Edge; //表示边的存在状态(0,1,INF)

图结构

封装好顶点集和边集,用vertexNum表示顶点个数,edgeNum表示边的条数,isDirect表示是否是有向图

struct MGraph{ Vertex nodes[MaxNumber]; Edge edges[MaxNumber][MaxNumber]; int vertexNum; int edgeNum; bool isDirect; };

初始化图

把边集里面自己指向自己的边填为0,不同顶点之间的边填为无穷大,假设已确定所有顶点

void initGraph(MGraph* graph,int vNum,bool isDirect,DataType vertex[]){ graph->vertexNum=vNum; greph->edgeNum=0; graph->isDirect=isDirect; for(int i=0;i<vertexNum;i++){ //初始化顶点集 graph->nodes[i].id=i; graph->nodes[i].data=vertex[i]; for(int j=0;j<vertexNum;j++){ //初始化边集 if(i==j)graph->edges[i][j]=0; else graph->edges[i][j]=INFINITY; } } }

添加边

假设边有权重weight,若不是网络就填1,边的起点为v1(索引),边的终点为v2(索引),若是无向图,添加一条边要添加对应的相反的边

void InsertEdge(MGraph* graph,int v1,int v2,int weight){ graph->edges[v1][v2]=weight; if(!graph->isDirect){ graph->edges[v2][v1]=weight; } graph->edgeNum++; }

邻接表

边结构

实际上是边的弧头和弧尾表示一条出度边,包含边的权值weight(如果是无权图就不需要),顶点的编号(弧头在数组中的下标)id,指向下一个弧头的指针next

struct Edge{ int weight; int id; Edge* next; }

顶点结构

用顺序表存顶点,每个顶点包含编号id,顶点的数据data,顶点的第一条出度边(实际上是弧头)fitstEdge

struct Vertex{ int id; Datatype data; Edge* firstEdge; }

图结构

包含顶点集数组V,顶点数量vertexNum,边数量edgeNum,是否是有向图isDirect

struct LGreaph{ Vertex* nodes; int vertexNum; int edgeNum; bool isDirect; }

初始化图

给顺序表中的顶点初始化data和id,firstEdge初始化为NULL

void initGraph(LGraph* graph,bool isDirect,int vNum,int edgeNum,DataType vertex[]){ graph->isDirect=isDirct; graph->vertexNum=vNum; graph->edgeNum=0; for(int i=0;i<graph->vertexNum;i++){ //初始化顶点集 graph->nodes[i].id=i; graph->nodes[i].data=vertex[i]; graph->nodes[i].firstEdge=NULL; } }

添加边

用头插法插在出度链表的表头,维护edgeNum,如果是无向图,需要添加相反的出度边

Edge* createEdge(int w,int v){ Edge* e=malloc(sizeof(Edge)); e->weight=w; e->id=v; e->next=NULL; return e; } void InsertEdge(LGraph* graph,int weight,int v1,int v2){ Edge* e=createEdge(weight,v2); e->next=graph->nodes[v1].firstEdge; graph->nodes[v1].firstEdge=e; graph->edgeNum++; if(!graph->isDirect){ //添加相反的出度边 e=createEdge(weight,v1); e->next=graph->nodes[v2].firstEdge; graph->nodes[v2].firstEdge=e; } }

缺点:不方便统计入度

十字链表

CrossGraph主要解决有向图

若用逆邻接表存有向图,有n条边就需要存2n个边结构
用十字链表存有向图,有n条边只需要存n个边结构

边结构

一条边含弧尾节点的编号tail,弧头节点的编号head,指向tail下一条出度边的指针tailNext,指向head下一条入度边的指针headNext,边的权重weight

struct Edge{ int tail; Edge* tailNext; int head; Edge* headNext; }

顶点结构

一个顶点含顶点编号id,顶点数据data,指向第一条入度边的指针firtstIn,指向第一条出度边的指针firstOut

struct Vertex{ int id; DataType data; Edge* firstIn; Edge* firstOut; }

图结构

用顺序表存储顶点集

struct CGraph{ int vertexNum; int edgeNum; Vertex* nodes; }

初始化图

void initGraph(CGraph* graph,int vNum,DataType vertex[]){ graph->vertexNum=vNum; graph->edgeNum=0; for(int i=0;i<graph->vertexNum;i++){ //初始化顶点结构 graph->id=i; graph->nodes[i].data=vertex[i]; graph->nodes[i].firstIn=nullptr; graph->nodes[i].firstOut=nullptr; } }

添加边

用头插法插入入度链表和出度链表

void InsertEdge(CGraph* graph,int t,int h,int w){ Edge* e=(Edge*)Edge(sizeof(Edge)); if(!e)return; graph->edgeNum++; e->tail=t; e->head=h; e->weight=w; //头插法插入出度边 e->tailNext=graph->nodes[e->tail]->firstOut; graph->nodes[e->tail]->firstOut=e; //头查法插入入度边 e->headNext=graph->nodes[e->head]->firstIn; graph->nodes[e->head]->firstIn=e; }

遍历所有出度

只需要从firstOut开始,沿着tailNext遍历到NULL

void traversalOut(CGraph* graph,int v){ Edge* p=graph->nodes[v]->firstOut; while(p){ visit(p); //访问行为 p=p->tailNext; } }

遍历入度同理

遍历所有入度

只需要从firstIn开始,沿着headNext遍历到NULL

void traversalIn(CGraph* graph,int v){ Edge* p=graph->nodes[v]->firstIn; while(p){ visit(p); //访问行为 p=p->headNext; } }
版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/3/14 16:23:47

12、Windows Server 2016安全与身份验证全面指南

Windows Server 2016安全与身份验证全面指南 在当今数字化时代,服务器的安全与身份验证至关重要。Windows Server 2016提供了一系列强大的安全功能,可帮助企业保护其数据和系统免受各种威胁。本文将详细介绍Windows Server 2016中的一些关键安全特性及其配置方法。 1. 代码…

作者头像 李华
网站建设 2026/3/13 3:22:59

如何快速上手FDS:解决5大常见火灾分析难题

如何快速上手FDS&#xff1a;解决5大常见火灾分析难题 【免费下载链接】fds Fire Dynamics Simulator 项目地址: https://gitcode.com/gh_mirrors/fd/fds FDS火灾模拟软件是消防工程领域的专业工具&#xff0c;能够帮助工程师精确预测火灾发展过程和烟雾扩散路径。面对复…

作者头像 李华
网站建设 2026/3/15 4:43:37

Notepad--多行编辑7大实战技巧:从入门到精通的完整指南

Notepad--多行编辑7大实战技巧&#xff1a;从入门到精通的完整指南 【免费下载链接】notepad-- 一个支持windows/linux/mac的文本编辑器&#xff0c;目标是做中国人自己的编辑器&#xff0c;来自中国。 项目地址: https://gitcode.com/GitHub_Trending/no/notepad-- 还在…

作者头像 李华
网站建设 2026/3/13 7:04:50

RISC-V指令集陷阱处理机制全面讲解

RISC-V陷阱处理机制&#xff1a;从硬件中断到系统调用的底层逻辑你有没有想过&#xff0c;当你在嵌入式设备上调用printf()的时候&#xff0c;CPU 是如何“感知”这个请求&#xff0c;并安全地把控制权交给操作系统的&#xff1f;又或者&#xff0c;当一个定时器到达设定时间&a…

作者头像 李华
网站建设 2026/3/15 2:37:48

树莓派4 HDMI输出无显示问题排查指南

树莓派4 HDMI无显示&#xff1f;别慌&#xff0c;一步步带你查到底你有没有过这样的经历&#xff1a;满怀期待地插上树莓派4&#xff0c;接好电源和显示器&#xff0c;结果屏幕一片漆黑&#xff0c;“无信号”三个字冷冷地挂在角落&#xff1f;红灯亮了&#xff0c;绿灯也在闪&…

作者头像 李华
网站建设 2026/3/13 20:27:39

GPT-SoVITS + GPU加速:语音合成性能翻倍方案

GPT-SoVITS GPU加速&#xff1a;语音合成性能翻倍方案 在短视频创作、虚拟主播和个性化教育内容爆发的今天&#xff0c;一个现实问题摆在开发者面前&#xff1a;如何用最少的数据、最快的速度生成高度拟真的定制化语音&#xff1f;传统语音合成系统往往需要几十小时录音和数天…

作者头像 李华