图的基本操作

news/2024/12/25 14:05:24/文章来源:https://www.cnblogs.com/chengfushi/p/18530851

目录
  • 1.图
  • 2.图的结构体定义
  • 3.图的初始化
  • 4.添加顶点、删除顶点
    • 4.1添加顶点
    • 4.2删除顶点
  • 5.添加边、删除边
    • 5.1添加边
    • 5.2删除边
  • 6.打印图
  • 7.main函数

在生命旅途中,我们就像是一个个节点,被无数看不见的边相连。每一次的相识与相离,都在这张巨大的网络图中留下独特的印记。

1.图

图(graph)是一种非线性数据结构,由顶点(vertex)和边(edge)组成。我们可以将图 G 抽象地表示为一组顶点 V 和一组边 E 的集合。

接下来,我将使用C语言基于邻接矩阵来构建这张图

2.图的结构体定义

邻接矩阵是一种用于表示图中顶点之间关系的二维数组。在您提供的结构体定义中,GraphAdjMat 包含了三个成员:verticesadjMatsize。以下是如何使用这个结构体来表示图的简要说明:

  1. 顶点数组 vertices

    • 这是一个一维数组,用于存储图中的顶点信息。每个元素对应一个顶点,可以存储顶点的标识符或其他相关信息。
  2. 邻接矩阵 adjMat

    • 这是一个二维数组,用于表示图中顶点之间的连接关系。adjMat[i][j] 表示顶点 i 和顶点 j 之间的边的信息。通常,如果顶点 i 和顶点 j 之间有边,则 adjMat[i][j] 会被设置为1(或边的权重,如果是加权图的话),如果没有边,则设置为0。
  3. 顶点数量 size

    • 这是一个整数,表示图中当前的顶点数量。这个值用于在操作图时,知道邻接矩阵中哪些行和列是有效的。
/*  * @brief 使用邻接矩阵来实现图  * @Max_Size 图中最大顶点数量  * @param vertices 顶点数组  * @param adjMat 邻接矩阵  * @param size 图中顶点的数量  */
# define  Max_Size 255  
typedef struct  
{  int vertices[Max_Size];  int adjMat[Max_Size][Max_Size];  int size;  
}GraphAdjMat;

3.图的初始化

函数 CreateGraph 的功能是创建并初始化一个图结构,使用邻接矩阵来表示这个图。具体来说,这个函数执行以下操作:

  1. 动态分配内存:为 GraphAdjMat 结构体分配一块内存空间。
  2. 检查内存分配:如果内存分配失败,则返回 NULL
  3. 初始化邻接矩阵:将邻接矩阵中的所有元素设置为0,表示图中没有边。
  4. 设置顶点数量:将图中的顶点数量 size 设置为0,表示图是空的。
  5. 返回图结构:返回一个指向新创建并初始化的图结构的指针。

简而言之,CreateGraph 函数用于创建一个空的图,并准备好用于后续添加顶点和边的操作。

/*  * @brief 图的初始化  * @param 无  * @return 初始化后的图  */GraphAdjMat *CreateGraph()  
{  //为图创建存储空间  GraphAdjMat *graph = (GraphAdjMat *)malloc(sizeof(GraphAdjMat));  //如果内存分配失败,返回空值  if (graph == NULL)  {  return NULL;  }  //将邻接矩阵初始化为0  for (int i = 0; i < Max_Size; i++)  {  for (int j = 0; j < Max_Size; j++)  {  graph->adjMat[i][j] = 0;  }  }  //将图顶点数置0  graph->size = 0;  return graph;  
}

4.添加顶点、删除顶点

4.1添加顶点

函数 addVertice 的功能是向图结构中添加一个新的顶点。以下是这个函数的简要说明:

  1. 参数检查:函数首先检查图中是否还有空间添加新的顶点。如果 graph->size 已经等于 Max_Size,即图中顶点数已达到最大值,函数将打印一条消息并返回,不执行添加操作。

  2. 添加顶点:如果图中还有空间,函数将新顶点的值 val 添加到 graph->vertices 数组的当前 size 索引处,这个索引对应于图中的下一个空位置。

  3. 更新邻接矩阵:对于新添加的顶点,函数需要更新邻接矩阵。它遍历所有已存在的顶点,并设置新顶点与这些顶点之间的连接状态为0(表示没有边)。这是通过设置 graph->adjMat[n][i]graph->adjMat[i][n] 来实现的,其中 n 是新顶点的索引。

  4. 增加顶点计数:最后,函数通过增加 graph->size 的值来更新图中顶点的数量。

简而言之,addVertice 函数用于在图的 vertices 数组中添加一个新的顶点,并在邻接矩阵中为这个新顶点初始化与其他顶点之间的边的状态。

/*  * @brief 添加顶点  * @param graph 要添加顶点的图  * @param val 要添加的元素  * @return 无  */void addVertice(GraphAdjMat *graph,int val)  
{  //如果图满,退出程序  if (graph->size == Max_Size)  {  printf("图已满!\n");  return;  }  //添加第n个结点  int n = graph->size;  graph->vertices[n] = val;  //将第n个结点的行和列均置0  for (int i = 0; i < n; i++)  {  graph->adjMat[n][i] = graph->adjMat[i][n] = 0;  }  graph->size++;  }

4.2删除顶点

函数 deleteVertice 的功能是从图结构中删除指定索引位置的顶点。以下是这个函数的简要说明:

  1. 参数检查:函数首先检查传入的索引 index 是否有效。如果索引小于0或大于等于图中顶点的数量 graph->size,则表示索引越界,函数将打印一条错误消息并返回,不执行删除操作。

  2. 删除顶点:如果索引有效,函数将从 vertices 数组中删除索引为 index 的顶点。这是通过将 index 位置及其后面的所有顶点向前移动一个位置来实现的。

  3. 删除邻接矩阵中的行:对于邻接矩阵中索引为 index 的行,函数将该行及其后面的所有行向前移动一个位置,以删除对应的行。

  4. 删除邻接矩阵中的列:对于邻接矩阵中索引为 index 的列,函数将该列及其后面的所有列向前移动一个位置,以删除对应的列。

  5. 更新顶点计数:最后,函数通过减少 graph->size 的值来更新图中顶点的数量。

简而言之,deleteVertice 函数用于从图中删除指定索引的顶点,并相应地更新 vertices 数组和邻接矩阵,以保持图的一致性。

/*  * @brief 删除顶点  * @param graph 图  * @param index 删除顶点的索引  * @return 无  */void deleteVertice(GraphAdjMat *graph,int index)  
{  //处理索引越界的情况  if (index <0 || index >= graph->size)  {  printf("索引越界!\n");  return;  }  //将顶点删除  for (int i = index; i < graph->size - 1;i++)  {  graph->vertices[i] = graph->vertices[i + 1];  }  //删除行  for (int i = index; i < graph->size -1;i++)  {  for (int j = 0; j < graph->size; j++)  {  graph->adjMat[i][j] = graph->adjMat[i + 1][j];  }  }  //删除列  for (int i = 0; i < graph->size; i++)  {  for (int j = index; j < graph->size - 1;j++)  {  graph->adjMat[i][j] = graph->adjMat[i][j + 1];  }  }  //顶点个数减1  graph->size--;  
}

5.添加边、删除边

5.1添加边

函数 addEdge 的功能是向图中添加一条边,连接两个指定索引的顶点。以下是这个函数的简要说明:

  1. 参数检查:函数首先检查传入的两个索引 index1index2 是否有效。如果任一索引小于0或大于等于图中顶点的数量 graph->size,则表示索引非法,函数将打印一条错误消息并返回,不执行添加边的操作。

  2. 添加边:如果两个索引都有效,函数将在邻接矩阵中设置 index1index2 之间的连接状态。具体来说,它将 graph->adjMat[index1][index2]graph->adjMat[index2][index1] 都设置为1。这表示在顶点 index1 和顶点 index2 之间添加了一条双向连接的边。

简而言之,addEdge 函数用于在图中添加一条无向边,连接两个指定索引的顶点,并在邻接矩阵中相应地更新这两个顶点之间的连接状态。

/*  * @brief 添加边  * @param graph * @param index1 index2 要添加的两个边在vertics中的索引  * @return 无  */void addEdge(GraphAdjMat *graph,int index1,int index2)  
{  if (index1 < 0 || index1 >= graph->size || index2 < 0 || index2 >= graph->size)  {  printf("索引非法\n");  return;  }  //添加边  graph->adjMat[index1][index2] = 1;  graph->adjMat[index2][index1] = 1;  }

5.2删除边

函数 deleteEdge 的功能是从图中删除连接两个指定索引顶点之间的边。以下是这个函数的简要说明:

  1. 参数检查:函数首先检查传入的两个索引 index1index2 是否有效。如果任一索引小于0或大于等于图中顶点的数量 graph->size,则表示索引非法,函数将打印一条错误消息并返回,不执行删除边的操作。

  2. 删除边:如果两个索引都有效,函数将在邻接矩阵中将 index1index2 之间的连接状态设置为0。具体来说,它将 graph->adjMat[index1][index2]graph->adjMat[index2][index1] 都设置为0。这表示在顶点 index1 和顶点 index2 之间删除了一条双向连接的边。

简而言之,deleteEdge 函数用于在图中删除一条无向边,该边连接两个指定索引的顶点,并在邻接矩阵中相应地更新这两个顶点之间的连接状态。

/*  * @brief 删除边  * @param graph 图  * @param index1,index2 要删除的两个顶点之间的边在vertices中的索引  */void deleteEdge(GraphAdjMat *graph, int index1, int index2)  
{  if (index1 < 0 || index1 >= graph->size || index2 < 0 || index2 >= graph->size)  {  printf("索引非法\n");  return;  }  //添加边  graph->adjMat[index1][index2] = 0;  graph->adjMat[index2][index1] = 0;  
}

6.打印图

/*  * @brief 打印邻接矩阵  * @param graph 图  * @return 无  */void printGraph(GraphAdjMat *graph)  
{  //输出顶点  for (int i = 0; i < graph->size; i++)  {  printf("%d ",graph->vertices[i]);  }  printf("\n");  //打印边  for (int i = 0; i < graph->size; i++)  {  for (int j = 0; j < graph->size; j++)  {  printf("%d ",graph->adjMat[i][j]);  }  printf("\n");  }  
}

7.main函数

int main(void)  
{  GraphAdjMat *graph = CreateGraph();  //添加顶点  int arr[] = {1,2,3,4,5,6,7,8,9};  for (int i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)  {  addVertice(graph,arr[i]);  }  //添加边  /*  * 1 2 3     * 4 5 6     * 7 8 9     */    addEdge(graph,0,1);  addEdge(graph,1,2);  addEdge(graph,0,3);  addEdge(graph,1,4);  addEdge(graph,2,5);  addEdge(graph,3,4);  addEdge(graph,4,5);  addEdge(graph,3,6);  addEdge(graph,4,7);  addEdge(graph,5,8);  addEdge(graph,6,7);  addEdge(graph,7,8);  //打印图  printGraph(graph);  return 0;  
}

输出:

D:\develop\Ccode\Data_Structure_Learn\Map\cmake-build-debug\Map.exe
1 2 3 4 5 6 7 8 9
0 1 0 1 0 0 0 0 0
1 0 1 0 1 0 0 0 0
0 1 0 0 0 1 0 0 0
1 0 0 0 1 0 1 0 0
0 1 0 1 0 1 0 1 0
0 0 1 0 1 0 0 0 1
0 0 0 1 0 0 0 1 0
0 0 0 0 1 0 1 0 1
0 0 0 0 0 1 0 1 0Process finished with exit code 0

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

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

相关文章

正态分布

正态分布 1 标准正态分布 1.1概率密度函数 \[f(x) = \frac{1}{\sqrt{2\pi}}e^{-\frac{x^2}{2}} \]1.2 累计分布函数 \[F(x) = \frac{1}{\sqrt{2\pi}} \int_{-\infty}^{x}e^{-\frac{t^2}{2}}dt \] 2 (一般)正态分布 2.1 概率密度函数 \[f(x) = \frac{1}{\sqrt{2\pi\sigma…

Pycharm中使用AI辅助Coding工具Aws Toolkit

一、安装插件 二、重启完了以后点击左下角的aws 三、点developer tools,双击codewhisperer中的start,点击connect 四、点击sign out,open and copy code五、跳转到网页浏览器中打开登录界面,我们在图中所示的 code 一栏中粘贴上验证码,点击"next"按钮六、没有账…

【日志分析平台】Logstash:IT-ELK日志分析平台

以下文章来源于唯云轩 ,作者唯云轩 上篇介绍了ELK日志分析平台-Elasticsearch集群的搭建,本篇章为大家介绍Logstash的安装 服务器规划及Elasticsearch集群搭建参考上一篇:IT-ELK日志分析平台-Elasticsearch集群 Logstash安装步骤如下官网下载安装包下载地址: (https://www.e…

Next 设置字体文件cdn 或者本地

@font-face {font-family: font-ali-bold;src: url(https://cdnurl/Alibaba-PuHuiTi-Bold.woff2) format(woff2);font-weight: normal;font-style: normal; }tailwind 设置 fontFamily 直接使用变量, 直接在className上写 font-ali 即可应用该字体 本地:// const aliF…

WPF的入门学习

环境的搭配 我们通过VS的官网来安装的VS2022,安装上C#的功能,这样就完成了环境的搭配 第一个wpf工程 打开vs2022,点击如图的创建新的工程。点选WPF的项目配置一个新的项目这样就完成了项目的创建项目结构 介绍一下大概的项目结构在APP.XAml文件中,设置我们的窗体入口界面的…

【安全架构】权限控制模型

原创 大袤宏图不同的权限模型提供了灵活的访问控制策略,本文绘制了不同模型的ER图,探讨这些模型的原理及适用场景。 一、访问控制列表模型 访问控制列表模型(Access Control List, ACL) 基于资源的访问控制列表,每个资源都有一个列表记录哪些用户可以对其进行哪些操作,适用…

不用代码,2小时搞定自己的网站

之前有许多人咨询过怎么建个官网,有没有 便宜,省事,且数据由自己掌控的方式。 毕竟一个企业在初期,如果不是IT行业,不一定有程序员,但是数据由自己掌握,未来发展壮大了,人员角色被齐了,就可以在原来的基础上做更好的发展了。 最近我也把玩了一个自助建站的产品,快速试…

PentesterTools:简单的SQLMap图形化辅助工具

原创 XiaoTouMingyo Hack分享吧免责声明 该公众号分享的安全工具和项目均来源于网络,仅供安全研究与学习之用,如用于其他用途,由使用者承担全部法律及连带责任,与工具作者和本公众号无关。工具介绍 SQLmap辅助工具是一款图形用户界面(GUI)工具,旨在简化和增强SQLmap的使…

【Xshell】高级用法: “隧道转发”

原创 大龙山悟道 IT运维不跑路xshell隧道转发类型 类型一:本地拨出 Local(Outgoing)作用:将本地计算机指定的某个端口连接到远程服务器的一个指定端口上。 应用场景:当从本地机器安全地访问位于远程服务器上的服务(如数据库、web服务等)时使用。 工作原理:通过SSH连接,用…

【安全运维】检测即代码(DAC) 详细步骤

原创 Zafkie1 SecLink安全空间引言 DAC(Detection As Code),检测即代码是一种战略方法,可将安全检测机制无缝集成到软件开发生命周期中。通过将安全控制视为代码,组织可以在整个SIEM运维过程中自动部署、配置和维护安全措施。 或许很多人听说过DAC的概念,但是并没有一步步地…

有道领世视频课程下载工具,如何在电脑端下载有道领世视频课程到本地?

一. 安装有道领世课程下载器 1.获取学无止下载器 https://www.xuewuzhi.cn/ydshengxue_downloader 2.下载安装后,然后点击桌面快捷方式运行即可。 注意:杀毒软件可能会阻止外部exe文件运行,并将其当做成病毒,直接添加信任即可,本软件绝对没有木马病毒。 二. 使用说明 1.学…

chapter15

relocation.py参数第一题问题用种子 1、2 和 3 运行,并计算进程生成的每个虚拟地址是处于界限内还是界限外?如果在界限内,请计算地址转换。 种子为1时:种子为2时:种子为3时:第二题问题使用以下标志运行:-s 0 -n 10。为了确保所有生成的虚拟地址都处于边界内,要将-l(界…