【数据结构第 6 章 ②】- 用 C 语言实现邻接矩阵

目录

一、邻接矩阵表示法

二、AMGraph.h

三、AMGraph.c

四、Test.c


【数据结构第 6 章 ① 】- 图的定义和基本术语-CSDN博客

由于图的结构比较复杂,任意两个顶点之间都可能存在联系,因此无法以数据元素在存储区中的物理位置来表示元素之间的关系,即图没有顺序存储结构,但可以借助二维数组来表示元素之间的关系,即邻接矩阵表示法。另一方面,由于图的任意两个顶点间都可能存在关系,因此,用链式存储表示图是很自然的事,图的链式存储有多种,有邻接表、十字链表和邻接多重表,应根据实际需要的不同,选择不同的存储结构。


一、邻接矩阵表示法

邻接矩阵(Adjacency Matrix)是表示顶点之间相邻关系的矩阵。设 G(V, E) 是具有 n 个顶点的图,则 G 的邻接矩阵是具有如下性质的 n 阶方阵

例如,图一中的 G1 和 G2 的邻接矩阵如下所示:

若 G 是网,则邻接矩阵可以定义为:

其中 w_{i, j} 表示边上的权值;​\infty 表示计算机允许的,大于所有边上权值的数。例如,下图所示为一个有向网和它的邻接矩阵。


二、AMGraph.h

用邻接矩阵表示法表示图,除了一个用于存储邻接矩阵的二维数组外,还需要用一个一维数组来存储顶点信息

注意:下面是以无向图为例的

#pragma once#define DEFAULT_CAPACITY 10typedef char VertexType;  // 假定顶点的数据类型为 char
typedef int EdgeType;  // 假定边的权值的数据类型为 inttypedef struct AMGraph
{VertexType* vertices;  // 顶点表(vertices 是 vertex 的复数)EdgeType** edges;  // 邻接矩阵int vSize;  // 当前图中的顶点数int eSize;  // 当前图中的边数int capacity;  // 容量
}AMGraph;// 基本操作
void AMGraphInit(AMGraph* pg);  // 初始化void ShowAdjMatrix(AMGraph* pg);  // 显示邻接矩阵int GetVetexPos(AMGraph* pg, VertexType v);  // 获取顶点的位置void InsertVertex(AMGraph* pg, VertexType v);  // 插入顶点
void InsertEdge(AMGraph* pg, VertexType v1, VertexType v2);  // 插入边void EraseVertex(AMGraph* pg, VertexType v);  // 删除顶点
void EraseEdge(AMGraph* pg, VertexType v1, VertexType v2);  // 删除边int GetFirstAdjVexPos(AMGraph* pg, VertexType v);  // 获取 v 的第一个邻接顶点的位置
int GetNextAdjVexPos(AMGraph* pg, VertexType v, VertexType w);
// 获取 v 的(相对于 w 的)下一个邻接顶点的位置void AMGraphDestroy(AMGraph* pg);  // 销毁


三、AMGraph.c

  1. 初始化

    void AMGraphInit(AMGraph* pg)
    {assert(pg);pg->vSize = pg->eSize = 0;pg->capacity = DEFAULT_CAPACITY;pg->vertices = (VertexType*)malloc(sizeof(VertexType) * pg->capacity);assert(pg->vertices);pg->edges = (EdgeType**)malloc(sizeof(EdgeType*) * pg->capacity);assert(pg->edges);for (int i = 0; i < pg->capacity; ++i){pg->edges[i] = (EdgeType*)malloc(sizeof(EdgeType) * pg->capacity);assert(pg->edges[i]);for (int j = 0; j < pg->capacity; ++j){pg->edges[i][j] = 0;}}
    }
  2. 获取顶点的位置

    int GetVetexPos(AMGraph* pg, VertexType v)
    {assert(pg);for (int i = 0; i < pg->vSize; ++i){if (pg->vertices[i] == v)return i;}return -1;
    }
  3. 显示邻接矩阵

    void ShowAdjMatrix(AMGraph* pg)
    {assert(pg);printf("  ");  // 输出两个空格for (int i = 0; i < pg->vSize; ++i){printf("%c ", pg->vertices[i]);}printf("\n");for (int i = 0; i < pg->vSize; ++i){printf("%c ", pg->vertices[i]);for (int j = 0; j < pg->vSize; ++j){printf("%d ", pg->edges[i][j]);}printf("\n");}
    }
  4. 插入顶点

    void InsertVertex(AMGraph* pg, VertexType v)
    {assert(pg);// 考虑是否需要扩容if (pg->vSize == pg->capacity){VertexType* tmp1 = (VertexType*)realloc(pg->vertices, sizeof(VertexType) * 2 * pg->capacity);assert(tmp1);pg->vertices = tmp1;EdgeType** tmp2 = (EdgeType**)realloc(pg->edges, sizeof(EdgeType*) * 2 * pg->capacity);assert(tmp2);pg->edges = tmp2;for (int i = 0; i < pg->capacity; ++i){EdgeType* tmp3 = (EdgeType*)realloc(pg->edges[i], sizeof(EdgeType) * 2 * pg->capacity);assert(tmp3);pg->edges[i] = tmp3;for (int j = pg->capacity; j < 2 * pg->capacity; ++j){pg->edges[i][j] = 0;}}for (int i = pg->capacity; i < 2 * pg->capacity; ++i){pg->edges[i] = (EdgeType*)malloc(sizeof(EdgeType) * 2 * pg->capacity);assert(pg->edges[i]);for (int j = 0; j < 2 * pg->capacity; ++j){pg->edges[i][j] = 0;}}pg->capacity *= 2;}// 插入顶点pg->vertices[pg->vSize++] = v;
    }
  5. 插入边

    void InsertEdge(AMGraph* pg, VertexType v1, VertexType v2)
    {assert(pg);int pos1 = GetVetexPos(pg, v1);int pos2 = GetVetexPos(pg, v2);if (pos1 == -1 || pos2 == -1)return;if (pg->edges[pos1][pos2] != 0)return;pg->edges[pos1][pos2] = pg->edges[pos2][pos1] = 1;++pg->eSize;
    }
  6. 删除顶点

    void EraseVertex(AMGraph* pg, VertexType v)
    {assert(pg);int pos = GetVetexPos(pg, v);if (pos == -1)return;// cnt 为和 v 相关联的边的数目int cnt = 0;for (int j = 0; j < pg->vSize; ++j){if (pg->edges[pos][j] != 0)++cnt;}pg->vertices[pos] = pg->vertices[pg->vSize - 1];for (int j = 0; j < pg->vSize; ++j){pg->edges[pos][j] = pg->edges[pg->vSize - 1][j];}for (int i = 0; i < pg->vSize; ++i){pg->edges[i][pos] = pg->edges[i][pg->vSize - 1];}--pg->vSize;pg->eSize -= cnt;
    }
    
  7. 删除边

    void EraseEdge(AMGraph* pg, VertexType v1, VertexType v2)
    {assert(pg);int pos1 = GetVetexPos(pg, v1);int pos2 = GetVetexPos(pg, v2);if (pos1 == -1 || pos2 == -1)return;if (pg->edges[pos1][pos2] == 0)return;pg->edges[pos1][pos2] = pg->edges[pos2][pos1] = 0;--pg->eSize;
    }
  8. 获取 v 的第一个邻接顶点

    int GetFirstAdjVexPos(AMGraph* pg, VertexType v)
    {assert(pg);int pos = GetVetexPos(pg, v);if (pos == -1)return -1;for (int j = 0; j < pg->vSize; ++j){if (pg->edges[pos][j] != 0)return j;}return -1;
    }
  9. 获取 v 的(相对于 w 的)下一个邻接顶点

    int GetNextAdjVexPos(AMGraph* pg, VertexType v, VertexType w)
    {assert(pg);int pos1 = GetVetexPos(pg, v);int pos2 = GetVetexPos(pg, w);if (pos1 == -1 || pos2 == -1)return -1;for (int j = pos2 + 1; j < pg->vSize; ++j){if (pg->edges[pos1][j] != 0)return j;}return -1;
    }
  10. 销毁

    void AMGraphDestroy(AMGraph* pg)
    {assert(pg);free(pg->vertices);pg->vertices = NULL;for (int i = 0; i < pg->capacity; ++i){free(pg->edges[i]);pg->edges[i] = NULL;}free(pg->edges);pg->edges = NULL;pg->vSize = pg->eSize = pg->capacity = 0;
    }


四、Test.c

#include "AMGraph.h"
#include <stdio.h>int main()
{AMGraph g;AMGraphInit(&g); InsertVertex(&g, 'A');InsertVertex(&g, 'B');InsertVertex(&g, 'C');InsertVertex(&g, 'D');InsertVertex(&g, 'E');InsertEdge(&g, 'A', 'B');InsertEdge(&g, 'A', 'D');InsertEdge(&g, 'B', 'C');InsertEdge(&g, 'B', 'E');InsertEdge(&g, 'C', 'D');InsertEdge(&g, 'C', 'E');ShowAdjMatrix(&g);printf("\n");EraseVertex(&g, 'C');ShowAdjMatrix(&g);printf("\n");EraseEdge(&g, 'A', 'B');ShowAdjMatrix(&g);printf("\n");printf("%d\n", GetFirstAdjVexPos(&g, 'A'));  // 3printf("%d\n", GetNextAdjVexPos(&g, 'A', 'D'));  // -1AMGraphDestroy(&g);return 0;
}

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

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

相关文章

SpringCloud网关介绍

一、Gateway简介 1、官网 上一代zuul 1.X&#xff1a;https://github.com/Netflix/zuul/wiki 当前gateway&#xff1a;https://cloud.spring.io/spring-cloud-static/spring-cloud-gateway/2.2.1.RELEASE/reference/html/ 2、是什么 SpringCloud Gateway是SpringCloud的一个全…

.NET Core 依赖注入 Microsoft.Extensions.DependencyInjection

文章目录 前言什么是依赖注入C# 使用依赖注入框架介绍 Microsoft.Extensions.DependencyInjectionNuget安装简单单例使用打印结果 自动装配举例自动装配测试用例打印结果自动装配执行顺序测试用例有歧义构造函数渐进式构造函数循环依赖 自动装配结论 手动装配手动注入别名注入 …

调用win32 api获取电脑名字和系统目录

学习一下几个函数的功能&#xff0c;和调用方式&#xff1b; void CBasenameView::OnDraw(CDC* pDC) {CBasenameDoc* pDoc GetDocument();ASSERT_VALID(pDoc);// TODO: add draw code for native data hereCString str1;TCHAR myname1[50], myname2[50], mydirname1[50], myd…

常见的Linux系统版本

在介绍常见的Linux系统版本之前&#xff0c;首先需要区分Linux系统内核与Linux发行套件系统的不同。Linux系统内核指的是一个由Linus Torvalds负责维护&#xff0c;提供硬件抽象层、硬盘及文件系统控制及多任务功能的系统核心程序。而Linux发行套件系统是我们常说的Linux操作系…

【Vue+Python】—— 基于Vue与Python的图书管理系统

文章目录 &#x1f356; 前言&#x1f3b6;一、项目描述✨二、项目展示&#x1f3c6;三、撒花 &#x1f356; 前言 【VuePython】—— 基于Vue与Python的图书管理系统 &#x1f3b6;一、项目描述 描述&#xff1a; 本项目为《基于Vue与Python的图书管理系统》&#xff0c;项目…

Minio保姆级教程

转载自&#xff1a;www.javaman.cn Minio服务器搭建和整合 1、centos安装minio 1.1、创建安装目录 mkdir -p /home/minio1.2、在线下载minio #进入目录 cd /home/minio #下载 wget https://dl.minio.io/server/minio/release/linux-amd64/minio1.3、minio配置 1.3.1、添加…

Flutter笔记:滑块及其实现分析1

Flutter笔记 滑块分析1 作者&#xff1a;李俊才 &#xff08;jcLee95&#xff09;&#xff1a;https://blog.csdn.net/qq_28550263 邮箱 &#xff1a;291148484163.com 本文地址&#xff1a;https://blog.csdn.net/qq_28550263/article/details/134900784 本文从设计角度&#…

SQL命令---删除字段

介绍 使用sql语句删除表字段。 命令 alter table 表名 drop 字段名;例子 删除a表中的name字段。 alter table a drop name;下面是执行删除后的表结构&#xff1a;

微服务实战系列之通信

前言 掰个指头数一数&#xff0c;博主的“微服务实战系列”从无到有&#xff0c;从零走到了十五。如果比作时钟&#xff0c;刚好走过了一刻度。 当初为什么要做这个系列&#xff0c;博主想了又想&#xff0c;私以为作为当下软件领域的几个“hot spot”之一&#xff0c;又乘着…

探秘机器学习核心逻辑:梯度下降的迭代过程 (图文详解)

一 需求解函数 f() 和 g()函数分别为求y值和求导数的函数。 目的&#xff1a;求该函数的最小值&#xff1a; 代码&#xff1a; import numpy as np import matplotlib.pyplot as plt f lambda x : (x - 3.5) ** 2 - 4.5 * x 10 g lambda x : 2 * (x - 3.5) - 4.5x np.l…

架构LAMP

目录 1.什么是LAMP 2.LAMP组成及作用 3.搭建Apache httpd服务 4.编译安装mysqld 服务 5.编译安装PHP 解析环境 6.安装论坛 1.什么是LAMP LAMP架构是目前成熟的企业网站应用模式之一&#xff0c;指的是协同工作的一整套系统和相关软件&#xff0c;能够提供动态Web站点服务…

【Python】视频剪辑小程序

近期遇到一些录制的视频需要剪辑。 手机上剪辑操作很耗时&#xff0c;有几个G的视频&#xff0c;花了一天的空余时间去剪辑。电脑上也有格式工厂&#xff0c;有很方便。 可是学了Pthon&#xff0c;又无意中了解到了moviepy这个库&#xff0c;于是自己写了个简单的视频剪辑程序。…

Windows安装kafka

压缩包下载地址&#xff1a;https://www.apache.org/dyn/closer.cgi?path/kafka/3.6.1/kafka_2.13-3.6.1.tgz 启动kafka步骤 zookeeper-server-start.bat rem 闭命令提示符窗口的命令回显&#xff0c;这样在运行脚本时不会显示脚本的具体命令内容 echo offrem 命令行启动未…

Proteus仿真--8×8LED点阵屏仿电梯数字滚动显示

本文介绍基于88LED点阵屏仿电梯数字滚动显示设计&#xff08;完整仿真源文件及代码见文末链接&#xff09; 仿真图如下 其中K1-K5的5个按键分别代表不同楼层&#xff0c;摁下按键后在8X8LED上便会显示到对应楼层的跳变信息&#xff0c;模拟电梯的运作 仿真运行视频 Proteus仿…

《安富莱嵌入式周报》第328期:自主微型机器人,火星探测器发射前失误故障分析,微软推出12周24期免费AI课程,炫酷3D LED点阵设计,MDK5.39发布

周报汇总地址&#xff1a;嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 更新一期视频教程&#xff1a; 【实战技能】 单步运行源码分析&#xff0c;一期视频整明白FreeRTOS内核源码框架和运行…

【STM32】TIM定时器基本定时功能

第一部分&#xff1a;定时器基本定时的功能&#xff1b; 第二部分&#xff1a;定时器的输出比较功能&#xff1b; 第三部分&#xff1a;定时器输入捕获的功能&#xff1b; 第四部分&#xff1a;定时器的编码接口。 1 TIM简介 TIM&#xff08;Timer&#xff09;定时器&#…

在OpenCV基于深度学习的超分辨率模型实践

1. 引言 OpenCV是一个开源的计算机视觉库&#xff0c;拥有大量优秀的算法。基于最新的合并&#xff0c;OpenCV包含一个易于使用的接口&#xff0c;主要用于实现基于深度学习方法的超分辨率&#xff08;SR&#xff09;。该接口包含预先训练的模型&#xff0c;这些模型可以非常容…

redis中使用事务保护数据完整性

事务是指一个执行过程&#xff0c;要么全部执行成功&#xff0c;要么失败什么都不改变。不会存在一部分成功一部分失败的情况&#xff0c;也就是事务的ACID四大特性&#xff08;原子性、一致性、隔离性、持久性&#xff09;。但是redis中的事务并不是严格意义上的事务&#xff…

智能优化算法应用:基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码

智能优化算法应用&#xff1a;基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码 文章目录 智能优化算法应用&#xff1a;基于蝗虫算法3D无线传感器网络(WSN)覆盖优化 - 附代码1.无线传感网络节点模型2.覆盖数学模型及分析3.蝗虫算法4.实验参数设定5.算法结果6.参考文献7.MA…

持续集成交付CICD:使用Maven命令上传Nexus制品

目录 一、实验 1.使用Maven命令上传Nexus制品&#xff08;第一种方式&#xff09; 2.使用Maven命令上传Nexus制品&#xff08;第二种方式&#xff09; 一、实验 1.使用Maven命令上传Nexus制品&#xff08;第一种方式&#xff09; &#xff08;1&#xff09;指定一个 hoste…