邻接矩超详解(C/C++)
提示:记得点赞,关注,收藏
目录
前言
一、领接矩阵
1.概念
2.分类
3.步骤
4. 邻接矩阵的优缺点
5.代码
前言
图的结构比较复杂,任何两个顶点之间都可能有关系。如果采用顺序存储,则需要使用二维数组表示元素之间的关系,即邻接矩阵(Adjacency Matrix),也可以使用边集数组,把,每条边顺序存储起来。如果采用链式存储,则有邻接表.十字链表和邻接多重表等表示方法。其中,邻接矩阵和邻接表是最简单、最常用的存储方法。。
提示:以下是本篇文章正文内容,本篇文章参考《算法训练营》
一、领接矩阵
1.概念
邻接矩阵通常采用一个一维数组存储图中节点的信息,采用一个二维数组存储图中节点之间的邻接关系。
2.分类
1. 邻接矩阵的表示方法
无向图、有向图和网的邻接矩阵的表示方法如下所述。
(1)无向图的邻接矩阵
在无向图中,若从节点vi 到节点vj 有边,则邻接矩阵 M [i ][j ]= M [j ][i ]=1,否则 M [i ][j ]=0。
例如,一个无向图的节点信息和邻接矩阵如下图所示。在该无向图中,从节点a 到节点b 有边,从节点b 到节点a 也有边,节点a 、b 在一维数组中的存储位置分别为0、1,则 M [0][1]= M [1][0]=1。
无向图的邻接矩阵的特点如下。
(1)无向图的邻接矩阵是对称矩阵,并且是唯一的。
(2)第i 行或第i 列非零元素的个数正好是第i 个节点的度。上图中的邻接矩阵,第3列非零元素的个数为2,说明第3个节点c 的度为2。
(2)有向图的邻接矩阵
在有向图中,若从节点vi 到节点vj 有边,则邻接矩阵 M [i ][j ]=1,否则 M [i ][j ]=0。
注意: 以尖括号<vi ,vj >表示的是有序对,以圆括号(vi ,vj )表示的是无序对,后同。
例如,一个有向图的节点信息和邻接矩阵如下图所示。在该有向图中,从节点a 到节点b 有边,节点a 、b 在一维数组中的存储位置分别为0、1,因此 M [0][1]=1。有向图中的边是有向边,从节点a 到节点b 有边,从节点b 到节点a 不一定有边,因此有向图的邻接矩阵不一定是对称的。
有向图的邻接矩阵的特点如下
(1)有向图的邻接矩阵不一定是对称的。
(2)第i 行非零元素的个数正好是第i 个节点的出度,第i 列非零元素的个数正好是第i 个节点的入度。上图中的邻接矩阵,第3行非零元素的个数为2,第3列非零元素的个数也为2,说明第3个节点c 的出度和入度均为2。
3)网的邻接矩阵
网是带权图,需要存储边的权值,则邻接矩阵表示为其中,wij 表示边上的权值,∞表示无穷大。当i =j 时,wii 也可被设置为0。
例如,一个网的节点信息和邻接矩阵如下图所示。在该网中,从节点a 到节点b 有边,且该边的权值为2,节点a 、b 在一维数组中的存储位置分别为0、1,因此 M [0][1]=2。从节点b 到节点a 没有边,因此 M [1][0]=∞。
3.步骤
算法步骤:
(1)输入节点数和边数;
(2)依次输入节点信息,将其存储到节点数组Vex[]中;
(3)初始化邻接矩阵,如果是图,则将其初始化为0;如果是网,则将其初始化为∞;
(4)依次输入每条边依附的两个节点,如果是网,则还需要输入该边的权值。
• 如果是无向图,则输入a b ,查询节点a、b 在节点数组Vex[]中的存储下标i 、j ,令Edge[i ][j ]=Edge[j ][i ]=1。
• 如果是有向图,则输入a b ,查询节点a、b 在节点数组Vex[]中的存储下标i 、j ,令Edge[i ][j ]=1。
• 如果是无向网,则输入a b w ,查询节点a、b 在节点数组Vex[]中的存储下标i 、j ,令Edge[i ][j ]=Edge[j ][i ]=w 。
• 如果是有向网,则输入a b w ,查询节点a、b 在节点数组Vex[]中的存储下标i 、j ,令Edge[i ][j ]=w 。
完美图解: 一个无向图如下图所示,其邻接矩阵的存储过程如下所述。
(1)输入节点数和边数。
4 5
结果:G .vexnum=4、G .edgenum=5。
(2)输入节点信息,将其存入节点信息数组。
a b c d
(3)初始化邻接矩阵的值均为0,如下图所示。
(4)依次输入每条边依附的两个节点。
• 输入a b ,处理结果:在Vex[]数组中查找到节点a 、b 的下标分别为0、1,是无向图,因此令 Edge[0][1]=Edge[1][0]=1,如下图所示。
• 输入a d ,处理结果:在Vex[]数组中查找到节点a 、d 的下标分别为0、3,是无向图,因此令Edge[0][3]= Edge[3][0]=1,如下图所示。
• 输入b c ,处理结果:在Vex[]数组中查找到节点b 、c 的下标分别为1、2,是无向图,因此令Edge[1][2]= Edge[2][1]=1,如下图所示。
• 输入b d ,处理结果:在Vex[]数组中查找到节点b 、d 的下标分别为1、3,是无向图,因此令Edge[1][3]= Edge[3][1]=1,如下图所示。
• 输入c d ,处理结果:在Vex[]数组中查找到节点c 、d 的下标分别为2、3,是无向图,因此令Edge[2][3]= Edge[3][2]=1,如下图所示。
在实际应用中,也可以先输入节点信息并将其存入数组Vex[]。在输入边时直接输入节点的存储下标序号,这样可以节省查询节点下标所需的时间,从而提高效率。
4. 邻接矩阵的优缺点
(1)优点如下。
• 快速判断在两节点之间是否有边。在图中,Edge[i ][j ]=1,表示有边;Edge[i ][j ]=0,表示无边。在网中,Edge[i ][j ]=∞,表示无边,否则表示有边。时间复杂度为O (1)。
• 方便计算各节点的度。在无向图中,邻接矩阵第i 行元素之和就是节点i 的度;在有向图中,第i 行元素之和就是节点i 的出度,第i 列元素之和就是节点i 的入度。时间复杂度为O (n )。
(2)缺点如下。
• 不便于增删节点。增删节点时,需要改变邻接矩阵的大小,效率较低。
• 不便于访问所有邻接点。访问第i 个节点的所有邻接点时,需要访问第i 行的所有元素,时间复杂度为O (n )。访问所有节点的邻接点,时间复杂度为O (n 2 )。
• 空间复杂度高,为O (n 2 )。
在实际应用中,如果在一个程序中只用到一个图,就可以用一个二维数组表示邻接矩阵,直接输入节点的下标,省去节点信息查询步骤。有时如果图无变化,则为了方便,可以省去输入操作,直接在程序头部定义邻接矩阵。
5.代码
领接矩阵存储结构创建
typedef char VexType; //顶点数最大值
typedef int EdgeType; //顶点的数据类型,根据需要定义
#define MaxVnum 100; //边上权值的数据类型,若不带权值,则为0或1
typedef struct
{VexType Vex[MaxVnum]; //存储顶点信息EdgeType Edge[MaxVnum][MaxVnum];int vexnum,edgenum; //顶点数,边数
} AMGragh;
无向图代码如下
//邻接矩阵创建无向图
#include <iostream>
using namespace std;#define MaxVnum 100 //顶点数最大值
typedef char VexType; //顶点的数据类型,根据需要定义
typedef int EdgeType; //边上权值的数据类型,若不带权值的图,则为0或1
typedef struct{VexType Vex[MaxVnum];EdgeType Edge[MaxVnum][MaxVnum];int vexnum,edgenum; //顶点数,边数
}AMGragh;int locatevex(AMGragh G,VexType x)
{for(int i=0;i<G.vexnum;i++)//查找顶点信息的下标if(x==G.Vex[i])return i;return -1;//没找到
}void CreateAMGraph(AMGragh &G)
{int i,j;VexType u,v;cout << "请输入顶点数:"<<endl;cin>>G.vexnum; //如果取的不是地址符号就要用G->vexnum cout << "请输入边数:"<<endl;cin>>G.edgenum;cout << "请输入顶点信息:"<<endl;for(int i=0;i<G.vexnum;i++)//输入顶点信息,存入顶点信息数组cin>>G.Vex[i];for(int i=0;i<G.vexnum;i++)//初始化邻接矩阵所有值为0,如果是网,则初始化邻接矩阵为无穷大for(int j=0;j<G.vexnum;j++)G.Edge[i][j]=0;cout << "请输入每条边依附的两个顶点:"<<endl;while(G.edgenum--){cin>>u>>v;i=locatevex(G,u);//查找顶点u的存储下标j=locatevex(G,v);//查找顶点v的存储下标if(i!=-1&&j!=-1)G.Edge[i][j]=G.Edge[j][i]=1; //邻接矩阵储置1else{cout << "输入顶点信息错!请重新输入!"<<endl;G.edgenum++;//本次输入不算}}
}void print(AMGragh G)//输出邻接矩阵
{cout<<"图的邻接矩阵为:"<<endl;for(int i=0;i<G.vexnum;i++){for(int j=0;j<G.vexnum;j++)cout<<G.Edge[i][j]<<"\t";cout<<endl;}
}int main()
{AMGragh G;CreateAMGraph(G);print(G);return 0;
}
邻接矩超详解(C/C++)相关推荐
- Android vector标签 PathData 画图超详解
此文章来源于https://www.cnblogs.com/yuhanghzsd/p/5466846.html点击打开链接 Android vector标签 PathData 画图超详解 SVG是一种 ...
- Mybatis案例超详解
Mybatis案例超详解 前言: 本来是想像之前一样继续跟新Mybatis,但由于种种原因,迟迟没有更新,快开学了,学了一个暑假,博客也更新了不少,我觉得我得缓缓,先整合一些案例练练,等我再成熟点理解 ...
- python控制手机模拟器_Appium+python自动化之连接模拟器并启动淘宝APP(超详解)...
简介 上一篇讲解完模拟器的安装.配置好以后,就好比我们手机已经买好,并且系统已经做好了,就差我们用数据线和电脑连接开始实战了,这篇宏哥就带着小伙伴们和童鞋们趁热打铁,讲解和分享一下如何连接模拟器(电脑 ...
- js打印三角形超详解
js打印三角形超详解 j控制星星的总行数,i控制每行星星的打印个数 打印图形如下: (1) (2) //str=""用来存储星星// 理解步骤1:在一行输出6个星星如何操作,在循环 ...
- 线性规划之单纯形法【超详解+图解】-转载
线性规划之单纯形法[超详解+图解] 目录 1.作用 2.线性规划的一般形式 5.1几何意义 5.2如何判断最优 5.3如何选择新的基变量 5.4如何选择被替换的基变量 5.5终止条件 标准型: 转化为 ...
- 【平衡小车制作】(七)串级PID调参及平衡成果展示(超详解)
大家好,我是小政.本篇文章我将针对PID调参进行详细的讲解,让每位小伙伴能够对比例.积分.微分三个参数如何调节有更加清晰的理解. 一.调参步骤 确立机械中值 直立环(内环)--Kp极性.Kp大小. ...
- 蓝牙模块XY-MBD07A的介绍及使用方法(超详解)
蓝牙模块XY-MBD07A的介绍及使用方法(超详解) 蓝牙XY-MBD07A是主从一体的蓝牙串口模块,简单的说,当蓝牙设备与蓝牙设备配对连接成功后,我们可以忽视蓝牙内部的通信协议,直接将将蓝牙当做串口 ...
- C/C++实现蛇形矩阵(超详解)【沈七】
C/C++实现蛇形矩阵(超详解) 题目链接 题目描述 输入样例 题解部分 完整代码 完结散花 悄悄告诉你: 参考文章 萌新报道! 唤我沈七就行嘿嘿. 大一软件工程在读. 菜鸡蒟蒻想在博客中记录一些算法 ...
- [C++ 系列] 90. 超详解C++思维导图
这段时间针对 C++ 的学习到了一个收尾的阶段.目前所涉及到了 C++ 基础语法.大小知识点的学习.当然语言学习绝对离不开实战项目的练手,网络优质资源以及各类经典丛书也是 C++ 学习的巨大宝库.在此 ...
最新文章
- python数据结构与算法:双向链表
- 关于PHP的 PHP-FPM进程CPU 100%的一些原因分析和解决方案
- c语言静态成员变量重名会怎么样,C++中静态成员函数与静态成员变量(static )...
- HDU-5023 线段树染色问题+延时标记
- 类模板 - C++快速入门45
- Q92:怎么对PLY文件对应的图形进行仿射变换
- java程序员专业技能_java程序员简历专业技能怎么写
- DroidCam通过数据线调用手机摄像头的方法二
- 定义Java中的方法及调用
- [****ViewController scrollViewDidScroll:]: message sent to deallocated instance 0x12d6c22f0
- centos8安装docker运行java文件
- Playing Atari with Deep Reinforcement Learning
- 移远4G模块通信模块使用
- JQuery实现图片自动轮播左右切换鼠标移入
- 接口自动化测试从入门到高级实战(最新干货)
- 项目管理工程师岗位职责
- 《A Byte of Python》PDF版电子书下载
- 35岁后,不是你被淘汰,而是你没有发现你的价值 | 如何发现35岁后的价值?
- SyntaxError: Non-ASCII character ‘\xe2‘ in file
- 软件设计师备考笔记(四) 数据库系统(重点)