当前位置: 首页 > news >正文

数据结构:图的存储与遍历(待续)

图(Graph)是一种较线性表和树更为复杂的非线性结构。在图结构中,对结点(图中常称为顶点)的前驱和后继个数不加限制, 即结点之间的关系是任意的。

一、基本概念和一般结论

13477d960fab4f0daf6e0470456f7a54.png
因为一条边关联两个顶点,而且使得这两个顶点的度数 分别增加1。因此顶点的度数之和就是边的两倍。

6cf67d371ede449e9043f50c392ed36f.png

关于连通图:

b669c912b6164173b42df7b7f7feda68.png

dad206945a8a4300b0670bd27c7b127f.png

无向图:连通图,连通子图,极大连通子图(连通分量,即一个图中最大的某个连通子图,即无法增加顶点以及边 使其构成更大的连通图)

有向图:强连通图,强连通子图,强连通分量。

连通分量不一定唯一。

二、图的存储结构

(1)邻接矩阵

6f57cc288c1f4f9a8e28d2783b1a24b4.png

邻接矩阵可以方便求出图中顶点的度:

对于邻接矩阵的第i行,如果其第j列有一个1(或者一个权值),则说明有一条边从vi指向vj。如果是有向图,则表示存在一条边<vi,vj>,通过行可以看出出度,通过列可以看出入度。


(2)邻接表

f6ca0085a9894a18bd46fa5ea8dffad1.pngcb53ffaf68c14e19967c0cf6b82f24f2.png

        总的来说就是,顺序存储图中的所有顶点信息,每个顶点信息包括顶点编号(也可以不用,因为顺序存储用数组标识的话,数组位置就是顶点编号),以及顶点的边链表头结点指针。一个顶点的边链表是将 以该顶点为起始的 连向的其他顶点信息。

       有向图的邻接表,边链表结点个数等于有向边的条数。(因为每条有向边有且仅有一个起始和一个终止)

        无向图的邻接表,边链表结点个数等于无向边的条数*2。(无向边是双向的)

7a5ff73cae74411e9ffe15ea88e1449b.png

struct Edge{//边链表结点int VerName;//顶点编号int cost;//边权值Edge *next;//指向下一个边链表结点
}
struct Vertex{//顶点表结点int VerName;//顶点编号Edge * adjacent;//边链表指针
}

(3)链式前向星

        实际上就是使用静态链表实现的邻接表。数据结构:静态链表(编程技巧)-CSDN博客

这样做的好处是,不需要使用指针,也不需要使用指针访问,直接通过数组下标即可访问,速度更快,内存更少。

插入表尾:

vector<int> head(n,-1);//n个顶点,head[i]指向边链表,初始都没有
vector<int> VerName;//边链表,adjacent[i]存的是边链表顶点信息
vector<int> next;//边链表的指针信息
vector<int> cost;//边的权值
/*可以理解为:
struct head{Edge* head[i];//head[i]表示的是第i个顶点的边链表表头。这里实际上是一个下标
}
struct Edge{//他们仨 下标是一样的int VerName;Edge* next;int cost;
};
*/
int Vertex;
int edge;
int cos;while(cin>>Vertex>>edge>>cos){//假定输入都是正确的,没有重边//为了复杂化,我们先找到边链表的最后一个结点int adj=head[Vertex];if(adj!=-1)while(next[adj]!=-1){adj=next[adj];}/*创建一个新结点 其之后无指向即next=-1*/VerName.push_back(edge);next.push_back(-1);cost.push_back(cos);/*-adj为Vertex边链表的最后一个元素-*/if(adj!=-1)next[adj]=next.size()-1;//VerName.size()-1、cost.size()-1均可 就是指向最后一个嘛。if(adj==-1){//只可能是顶点还没有边head[Vertex]=next.size()-1;}
}//顺次输出边
for(int i=0;i<n;++i){int adj=head[i];while(adj!=-1){cout<<i<<"--->"<<VerName[adj]<<"  cost为:"<<cost[adj]<<endl;adj=next[adj];}
}
//我们会发现,将adj当做一个结构体指针Edge *,那么VerName[adj]相当于adj->VerName了

直接插入表头:

while(cin>>Vertex>>edge>>cos){/*直接创建点,插入在Vertex的边链表表头*/VerName.push_back(edge);next.push_back(head[Vertex]);cost.push_back(cos);head[Vertex]=next.size()-1;
}

相关文章:

  • 同态滤波算法详解
  • Docker进阶:深入了解 Dockerfile
  • 采购代购系统独立站,接口采集商品上货
  • L1-039 古风排版(C++)
  • 基于YOLOv8/YOLOv7/YOLOv6/YOLOv5的条形码二维码检测系统(深度学习+UI界面+训练数据集+Python代码)
  • Oracle 死锁、指标汇总
  • 有点NB的免费wordpress主题模板
  • Neo4j 批量导入数据 从官方文档学习LOAD CSV 命令 小白可食用版
  • PHP+Lunix+GIT 如何快速使用宝塔WebHook快速自动化部署
  • C++训练营:引用传递
  • 计算机服务器中了devos勒索病毒怎么解密,devos勒索病毒解密工具流程
  • 【计算机网络教程】第一章课后习题答案
  • Websocket在Asp.net webApi(.net framework)上的应用
  • JAVA后端开发面试基础知识(九)——SpringBoot
  • 机器学习模型—逻辑回归
  • 【翻译】babel对TC39装饰器草案的实现
  • 3.7、@ResponseBody 和 @RestController
  • Angular2开发踩坑系列-生产环境编译
  • crontab执行失败的多种原因
  • ECMAScript入门(七)--Module语法
  • hadoop入门学习教程--DKHadoop完整安装步骤
  • iOS动画编程-View动画[ 1 ] 基础View动画
  • JavaScript 基础知识 - 入门篇(一)
  • Linux Process Manage
  • MySQL主从复制读写分离及奇怪的问题
  • Node 版本管理
  • SegmentFault 2015 Top Rank
  • springboot_database项目介绍
  • SQLServer之索引简介
  • 测试如何在敏捷团队中工作?
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 利用DataURL技术在网页上显示图片
  • 浅谈Golang中select的用法
  • 学习笔记TF060:图像语音结合,看图说话
  • 移动端 h5开发相关内容总结(三)
  • 用Visual Studio开发以太坊智能合约
  • CMake 入门1/5:基于阿里云 ECS搭建体验环境
  • 好程序员web前端教程分享CSS不同元素margin的计算 ...
  • # .NET Framework中使用命名管道进行进程间通信
  • #NOIP 2014#Day.2 T3 解方程
  • (07)Hive——窗口函数详解
  • (HAL库版)freeRTOS移植STMF103
  • (Matalb分类预测)GA-BP遗传算法优化BP神经网络的多维分类预测
  • (Redis使用系列) Springboot 在redis中使用BloomFilter布隆过滤器机制 六
  • (含react-draggable库以及相关BUG如何解决)固定在左上方某盒子内(如按钮)添加可拖动功能,使用react hook语法实现
  • (顺序)容器的好伴侣 --- 容器适配器
  • (一)Thymeleaf用法——Thymeleaf简介
  • (转) SpringBoot:使用spring-boot-devtools进行热部署以及不生效的问题解决
  • (转)Oracle 9i 数据库设计指引全集(1)
  • .NET 分布式技术比较
  • .NET/C# 中设置当发生某个特定异常时进入断点(不借助 Visual Studio 的纯代码实现)
  • .NET开发不可不知、不可不用的辅助类(三)(报表导出---终结版)
  • .skip() 和 .only() 的使用
  • [Angular 基础] - 数据绑定(databinding)
  • [Asp.net MVC]Asp.net MVC5系列——Razor语法