【数据结构】图之邻接矩阵代码实现与dfs、bfs

一、图的相关概念

图的相关概念包括顶点、边、有向图和无向图等。图是计算机科学中一个核心的数据结构,用于描述对象之间的关系。它由顶点(节点)的集合和连接这些顶点的边的集合组成。具体分析如下:

  1. 顶点:图中的基本构成单位,也称为节点或顶点
  2. :连接两个顶点的线段,可以是有向的或无向的,代表两个顶点之间的关系
  3. 有向图:边具有方向性,即从一个顶点指向另一个顶点,表示关系的非对称性
  4. 无向图:边没有方向,表示两个顶点之间的相互关系
  5. 完全图:每对不同顶点之间都恰好有一条边相连的图,分为有向完全图和无向完全图
  6. 邻接顶点:在无向图中,如果存在一条边直接连接两个顶点,则这两个顶点互为邻接顶点;在有向图中,如果存在一条边从顶点A指向顶点B,则称顶点B邻接自顶点A
  7. 顶点的度:与某个顶点相关联的边的总数,对于有向图来说,顶点的度等于其入度和出度之和
  8. 路径:一系列的顶点和边交替出现形成的序列,表示从一个顶点到另一个顶点的路线
  9. 简单路径与回路:路径上不重复访问同一个顶点的路径称为简单路径;如果起点和终点相同的路径称为回路
  10. 子图:如果一个图的顶点集和边集都是另一个图的子集,那么这个图就是另一个图的子图

除了上述基本概念外,图还有一些存储结构,如邻接矩阵和邻接表,以及遍历算法,如深度优先搜索(DFS)和广度优先搜索(BFS)。此外,图论中的一些经典问题包括最短路径问题、最小生成树问题、网络流问题等,它们都有对应的算法来解决。

综上所述,图是一种强大的数据结构,能够有效地模拟和解决现实世界中的许多问题,如社交网络分析、推荐系统、交通规划等。通过学习和掌握图的相关概念和算法,可以在多个领域内应用图的理论来优化问题解决方案。、

图的存储结构主要有邻接矩阵、邻接表、十字链表和邻接多重表。这些存储方法各有特点,适应不同类型的图和不同的操作需求。下面将具体介绍这几种存储结构:

  1. 邻接矩阵
    • 无向图的邻接矩阵:在这种表示法中,矩阵是对称的,即arcs[i][j]等于arcs[j][i],因为无向图中边没有方向
    • 有向图的邻接矩阵:在有向图的情况下,矩阵不对称,arcs[i][j]表示从顶点i到顶点j的边。
    • 网(有权图)的邻接矩阵:如果图中的边有权值,则邻接矩阵中的元素表示相应顶点之间边的权值
    • 邻接矩阵的存储表示:通常使用二维数组来实现,其中行和列代表图中的顶点,交叉点的值表示这两个顶点之间是否有边或权的值
  1. 邻接表
    • 无向图的邻接表表示:每个顶点对应一个链表,链表中包含与该顶点相邻的所有顶点。
    • 有向图的邻接表表示:在有向图中,邻接表显示为从每个顶点出发可以到达的顶点列表
    • 图的邻接表的存储定义:需要为每个顶点定义一个链表头节点,然后通过链表实现各顶点之间的连接关系
  1. 十字链表
    • 弧结点的结构:每个弧有一个结构来表示,其中包括弧的信息以及弧尾和弧头的位置信息。
    • 顶点结点的结构:每个顶点也有一个结构来表示,包括顶点信息及与该顶点相关联的弧的指针。
  1. 邻接多重表
    • 边结点的结构:在邻接多重表中,每条边使用一个结点表示[1]。
    • 图的结构定义:图的结点不仅包含顶点信息,还包括一个指向所有依附于该顶点的边的列表的头指针

针对上述分析,提出以下补充内容:

  • 邻接矩阵适合稠密图,可以快速判断两个顶点间是否有边。
  • 邻接表适合稀疏图,只存储存在的边,节省空间
  • 十字链表和邻接多重表提供了更加灵活的图表示方式
  • 对于带权图,存储结构需要扩展以保存权值信息

综上所述,图的存储结构根据图的类型和实际应用场景的不同而有所选择。在实际应用中,选择合适的存储结构对于提高算法效率和节约存储空间至关重要。

二、邻接矩阵

邻接矩阵是图的一种存储方式,适用于稠密图和小规模的图,它直接在矩阵中存储顶点间的邻接关系。具体分析如下:

  1. 存储方式
    • 创建一个二维数组(矩阵),其大小为顶点数乘以顶点数
    • 矩阵的行和列分别代表图中的所有顶点,相交的单元格表示两个顶点之间是否有边
  1. 无向图邻接矩阵
    • 邻接矩阵是对称的,如果顶点i与顶点j相连,则arcs[i][j]arcs[j][i]相等且均不为
  1. 有向图邻接矩阵
    • 邻接矩阵不对称,如果从顶点i到顶点j有一条边,那么arcs[i][j]等于1(或边的权值),而arcs[j][i]可能为0
  1. 网(有权图)的邻接矩阵
    • 邻接矩阵中的每个元素值代表对应顶点间边的权值,如果没有边则为无穷大或其他特殊值
  1. 空间复杂度
    • 空间复杂度为V^2,其中V是顶点的数量
  1. 时间复杂度
    • 判断任意两点是否相邻的时间复杂度为O(1),因为直接索引矩阵即可
  1. 优缺点
    • 优点包括容易实现,能快速判断顶点间是否存在边,易于编程
    • 缺点是占用空间大,尤其是对于稀疏图,会浪费很多存储空间
#include<iostream>
#include<algorithm>
using namespace std;const int N = 5;
const int MAX_VALUE = INT_MAX;typedef char ElemType;
typedef struct GraphMatrix {ElemType arrayV[N];  // 顶点数组int matrix[N][N];    // 邻接矩阵bool isDirect;       // 是否是有向图int size;            // 顶点个数
} GraphMatrix,* Graph;/*** 初始化* @param V 要构建的图的顶点数组* @param isDirect 是否为有向图* @param size 顶点个数* @return 这个图的地址*/
Graph initGraphMatrix(ElemType* V, bool isDirect, int size) {// 1. 创建图auto graph = (Graph) malloc(sizeof(GraphMatrix));// 2. 初始化字段graph->isDirect = isDirect;graph->size = size;for (int i = 0; i < size; i++) {graph->arrayV[i] = V[i];}// 3. 初始化邻接矩阵for (int i = 0; i < size; i++) {for (int j = 0; j < size; j++) {graph->matrix[i][j] = MAX_VALUE;}}// 4. 返回地址return graph;
}/*** 获取这个顶点的下标* @param graph* @param src*/
int getIndexOfV(Graph& graph, ElemType src) {// 1. 循环遍历,可以使用map进行优化for (int i = 0; i < graph->size; i++) {if (graph->arrayV[i] == src) {return i;}}return -1;
}/*** 添加一条变* @param graph 操作的图* @param src  起点* @param dest 终点* @param weight 权重*/
void addEdge(Graph& graph, ElemType src, ElemType dest, int weight) {// 1. 合法检验if (graph == nullptr) return;// 2. 查询两个顶点对应的邻接矩阵下标int srcIndex = getIndexOfV(graph, src);int destIndex = getIndexOfV(graph, dest);// 3. 判断下标合法if (srcIndex < 0 || destIndex < 0 || srcIndex > graph->size || destIndex > graph->size) return;// 4. 添加一条边graph->matrix[srcIndex][destIndex] = weight;// 5. 如果这是无向图则添加dest到srcif (!graph->isDirect) graph->matrix[destIndex][srcIndex] = weight;
}/*** 获取边的度* @param graph 图* @param V 边* @return*/
int getDevOfV(Graph& graph, ElemType V) {// 1. 合法判断if (graph == nullptr) return -1;// 2. 获取下标int index = getIndexOfV(graph, V);if (index < 0 || index > graph->size) return -1;// 2. 遍历邻接矩阵int cnt = 0;for (int i = 0; i < graph->size; i++) {if (graph->matrix[index][i] != MAX_VALUE) cnt++;if (!graph->isDirect && graph->matrix[i][index]) cnt++;}// 3. 返回度return cnt;
}/*** 打印矩阵* @param graph 图*/
void printGraph(Graph& graph) {for (int i = 0; i < graph->size; i++) {for (int j = 0; j < graph->size; j++) {if (graph->matrix[i][j] == MAX_VALUE) cout << "-" << "   ";else cout << graph->matrix[i][j] << "   ";}cout << "\n";}cout << "----------------------\n";
}/*** bfs* @param graph*/
void bfs(Graph& graph, ElemType src) {// 1. 合法校验if (graph == nullptr) return;// 2. 创建队列与visited数组bool visited[graph->size];int queue[graph->size << 1];int front = 0, rear = 0;// 3. 入队顶点int index = getIndexOfV(graph,src);if (index < 0 || index > graph->size) return;queue[rear++] = index;// 4. 开始bfswhile (front < rear) {int top = queue[front++];cout << graph->arrayV[top] << "->";for (int i = 0; i < graph->size; i++) {if (graph->matrix[top][i] != MAX_VALUE && !visited[i]) {queue[rear++] = i;visited[top] = true;}}}cout << "\n----------------------\n";
}/*** dfs* @param graph* @param src* @param visited*/
void dfsFun(Graph& graph, int src, bool* visited) {cout << graph->arrayV[src] << "->";visited[src] = true;for (int i = 0; i < graph->size; i++) {if (!visited[i] && graph->matrix[src][i] != MAX_VALUE) {dfsFun(graph, i, visited);}}
}/*** dfs* @param graph* @param src*/
void dfs(Graph& graph, ElemType src) {// 1. 合法校验if (graph == nullptr) return;// 2. dfs准备bool visited[graph->size];int index = getIndexOfV(graph, src);if (index < 0 || index > graph->size) return;// 3. dfsdfsFun(graph, index, visited);cout << "\n----------------------\n";
}/*** 克鲁斯卡尔算法  最小生成树* @param graph 图* @param ans graph的最小生成树* @return 最小生成树的权值和*/
int kruskal(Graph& graph, Graph& ans) {return -1;
}/*** Prim算法* @param graph 图* @param ans 最小生成树* @return 最小生成树的权值之和*/
int prim(Graph& graph, Graph& ans) {return -1;
}/*** 迪杰斯特拉算法* @param graph 图* @param src 起始顶点* @param dist 距离数组--最短路* @param path 路径数组--最短路*/
void dijkstra(Graph& graph, ElemType src, int* dist, int* path) {}/*** 贝尔曼算法* @param graph 图* @param src 起始顶点* @param dist 距离数组--最短路* @param path 路径数组--最短路* @return*/
bool bellmanFord(Graph& graph, ElemType src, int* dist, int *path) {return 0;
}/*** floyd算法* @param graph 图* @param dist 距离数组--多源最短路* @param path 距离数组--多源最短路*/
void floydWarShall(Graph& graph, int** dist, int** path) {}int main() {auto* V = (ElemType*) malloc(sizeof(ElemType) * 4);V[0] = 'A', V[1] = 'B', V[2] = 'C', V[3] = 'D';Graph graph = initGraphMatrix(V, true, 4);//    printGraph(graph);////    addEdge(graph, 'A', 'B', 1);//    addEdge(graph, 'A', 'C', 2);////    printGraph(graph);addEdge(graph, 'A', 'B', 1);addEdge(graph, 'B', 'D', 1);addEdge(graph, 'D', 'A', 1);printGraph(graph);bfs(graph, 'A');dfs(graph, 'A');return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/web/25770.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

linux 关于jq的安装和使用

文章目录 前言 一、jq是什么&#xff1f; 二、安装方法 1.在线安装 2.离线安装 三、使用方法 1. 读取json字符串并解析 2.读取json文件并解析 3.遍历json数组&#xff0c;查询姓名为Bob学生的年龄 总结 前言 今天要写一个自定义的脚本&#xff0c;涉及到对json数据的解…

SOA的设计模式_2.企业服务总线模式

1.企业服务总线&#xff08;|Enterprise Service Bus&#xff0c;ESB&#xff09; 在企业基于SOA实施EAI、B2B和BMP的过程中&#xff0c;如果采用点对点的集成方式存在着复杂度高&#xff0c;可管理性差&#xff0c;复用度差和系统脆弱等问题。企业服务总线&#xff08;…

【微信小程序】事件传参的两种方式

文章目录 1.什么是事件传参2.data-*方式传参3.mark自定义数据 1.什么是事件传参 事件传参:在触发事件时&#xff0c;将一些数据作为参数传递给事件处理函数的过程&#xff0c;就是事件传参 在微信小程序中&#xff0c;我们经常会在组件上添加一些自定义数据&#xff0c;然后在…

定个小目标之刷LeetCode热题(12)

这是一道简单题&#xff0c;使用位运算中的异或运算即可&#xff0c;异或运算有以下性质&#xff1a; 1、任何数异或 0 结果仍然是原来的数&#xff0c;即 a⊕0a 2、任何数和其自身做异或运算&#xff0c;结果是 0 所以我们只需要让数组里的所有元素进行异或运算得到的结果就…

oracle的bitmap索引是什么

Oracle的Bitmap索引是一种特殊的索引类型&#xff0c;主要用于处理那些数值稀疏&#xff08;low-cardinality&#xff0c;低基数&#xff09;的字段&#xff0c;特别是那些值不经常改变的字段。以下是关于Bitmap索引的详细解释&#xff1a; 定义&#xff1a; Bitmap索引是一种…

Python实现删除Word文档中带有“指定内容”的段落文本(7)

前言 本文是该专栏的第7篇,后面会持续分享Python办公自动化干货知识,记得关注。 在处理word文档内容的时候,有时候我们需要一个干净整洁的文本内容。比如说,如下图所示的情况: 在处理上述word文档内容的时候,我们希望将文本底部的“下载链接”以及“附件信息”两个段落,…

持续总结中!2024年面试必问 20 道分布式、微服务面试题(八)

上一篇地址&#xff1a;持续总结中&#xff01;2024年面试必问 20 道分布式、微服务面试题&#xff08;七&#xff09;-CSDN博客 十五、Docker和Kubernetes有什么区别&#xff1f; Docker 和 Kubernetes 是两个在容器化领域中非常流行的工具&#xff0c;但它们在功能和用途上…

每日算法——归并排序

什么是归并排序 归并排序是一种分治算法。它将数组不断地分成两半&#xff0c;对每一半进行排序&#xff0c;然后再将排序好的两半合并起来。通过不断重复这个过程&#xff0c;最终得到完全排序的数组。 归并排序的注意点&#xff1a; 空间复杂度&#xff1a;归并排序需要额…

MQ解决的问题

系统中MQ能解决哪些问题&#xff1f; 1.不同语言的程序使用MQ通信 2.分布式&#xff0c;微服务&#xff0c;之间的通信&#xff0c;实现服务质检解耦 3.高并发实现销峰作用 4.实现异步&#xff0c;提高用户体验。

浅谈AI-在公司资金管理中的应用

现在&#xff0c;随着人工智能&#xff08;AI&#xff09;技术的快速发展&#xff0c;越来越多的企业开始将其应用到资金管理中。AI在这方面不仅提高了效率和准确性&#xff0c;还大大减少了人为错误和操作风险。下面是AI在企业资金管理中的几种主要应用。 1. 预测未来资金流&…

Mysql使用中的性能优化——搭建Mysql的监测服务

大纲 环境安装配置Mysql安装设置root密码新增远程访问账户修改绑定地址重启 新增 MySQL Server Exporter 用户 安装启动mysqld_exporter安装启动新增配置启动直接启动以Service形式启动 安装启动Prometheus创建用户下载并解压修改配置启动 安装启动grafana安装启动 测试参考资料…

[数据集][图像分类]黑色素瘤分类数据集10015张7类别

数据集类型&#xff1a;图像分类用&#xff0c;不可用于目标检测无标注文件 数据集格式&#xff1a;仅仅包含jpg图片&#xff0c;每个类别文件夹下面存放着对应图片 图片数量(jpg文件个数)&#xff1a;10015 分类类别数&#xff1a;7 类别名称:[“0”,“1”,“2”,“3”,“4”,…

【博士每天一篇文献-综述】Modularity in Deep Learning A Survey

阅读时间&#xff1a;2023-12-8 1 介绍 年份&#xff1a;2023 作者&#xff1a;孙浩哲&#xff0c;布朗克斯医疗卫生系统 会议&#xff1a; Science and Information Conference 引用量&#xff1a;4 论文主要探讨了深度学习中的模块化&#xff08;modularity&#xff09;概念…

软件测试--Mysql快速入门

文章目录 软件测试-mysql快速入门sql主要划分mysql常用的数据类型sql基本操作常用字段的约束&#xff1a;连接查询mysql内置函数存储过程视图事务索引 软件测试-mysql快速入门 sql主要划分 sql语言主要分为&#xff1a; DQL&#xff1a;数据查询语言&#xff0c;用于对数据进…

传感器展会|2024厦门传感器与应用技术展览会

传感器展会|2024厦门传感器与应用技术展览会 时间&#xff1a;2024年11月1-3日 地点&#xff1a;厦门国际会展中心 XISE EXPO展会介绍&#xff1a; 2024中国&#xff08;厦门&#xff09;国际传感器与应用技术展览会将于2024年11月1-3日在厦门国际会展中心举行&#xf…

2024浙江省三支一扶报名流程!超详细图解!

2024浙江省三支一扶报名流程&#xff01;超详细图解&#xff01; 浙江省高校毕业生“三支一扶”报名即将开始&#xff0c;准备报考的同学们做好准备&#xff1a; &#x1f534;重点时间安排&#xff1a; 1、网络报名&#xff1a;6月11日9:00至6月18日17:00 2、资格审核&…

Selenium with Python Behave(BDD)

一、简介 Python语言的行为驱动开发&#xff0c;Behavior-driven development&#xff0c;简称BDD. "Behavior-driven development (or BDD) is an agile software development technique that encourages collaboration between developers, QA and non-technical or bu…

maven多模块项目搭建

文章目录 创建方式创建父项目创建子模块 目录结构示例父模块模块A模块B&#xff08;并在模块B中引入模块A&#xff09; 注意事项 创建方式 创建父项目 #创建文件夹后&#xff0c;进入目录&#xff0c;执行以下命令 PS D:\demo> mvn archetype:generate #将输出很多模板&am…

5 个你不知道的隐藏 CSS 属性

层叠样式表 (CSS) 是网页设计的骨架&#xff0c;它可以帮助我们轻松的设置网页的样式和格式。虽然大多数的 CSS 属性&#xff0c;例如颜色、字体大小和边距都被大家熟知&#xff0c;但还有许多鲜为人知的属性可以帮助我们设计添加功能。在这篇文章中&#xff0c;我们将介绍 5 个…

Hive 面试题(九)

1. 简述Hive的开窗函数有哪些 &#xff1f; Hive的开窗函数&#xff08;Window Functions&#xff09;是一种特殊的函数&#xff0c;它在某种程度上类似于聚合函数&#xff0c;但是它们为每一行返回一个值&#xff0c;而不是将多行合并为一个单一的聚合输出。开窗函数在处理数…