【数据结构第 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.hqwc.cn/news/267732.html

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

相关文章

anolisos8.8安装显卡+CUDA工具+容器运行时支持(containerd/docker)+k8s部署GPU插件

anolisos8.8安装显卡及cuda工具 一、目录 1、测试环境 2、安装显卡驱动 3、安装cuda工具 4、配置容器运行时 5、K8S集群安装nvidia插件 二、测试环境 操作系统&#xff1a;Anolis OS 8.8 内核版本&#xff1a;5.10.134-13.an8.x86_64 显卡安装版本&#xff1a;525.147.05 c…

el-tree搜索的使用

2023.12.11今天我学习了如何对el-tree进行搜索的功能&#xff0c;效果如下&#xff1a; <template><div class"head-container"><el-inputv-model"roleName"clearableplaceholder"请输入角色/用户名称"prefix-icon"el-icon-…

linux搭建seata并使用

搭建seata 官网 在linux下搭建 下载1.6.1版本&#xff1a;地址 新建文件夹、上传压缩包并解压 [roothao ~]# cd /usr/local/software/ [roothao /usr/local/software]# ls canal docker elk gitlab jdk mysql nacos nexus nginx rabbitmq redis redis_sentinel…

[IDEA] 写代码时没有类型推断的解决方法

本示例使用scala, 其他语言同理 使用 .var 时会自动生成变量 使用快捷键 CtrlAtlv 一样 val abc "abc"但是这个变量没有显式表现类型 期望 val abc: String "abc" 解决方法

[Unity]关于Unity接入Appsflyer并且打点支付

首先需要去官方下载Appsflyer的UnityPackage 链接在这afPackage 然后导入 导入完成 引入此段代码 using AppsFlyerSDK; using System.Collections; using System.Collections.Generic; using UnityEngine;public class AppflysManager : MonoBehaviour {public static App…

高效利用内存资源之动态内存管理详解

目录 一、为什么存在动态内存分配 二、动态内存函数的介绍 2.1malloc 2.2free 2.3calloc 2.4realloc 三、常见的动态内存错误 3.1对NULL指针的解引用操作 3.2对动态开辟空间的越界访问 3.3对非动态开辟内存使用free释放 3.4使用free释放一块动态开辟内存的一部分 3.…

UE4/UE5 修改/还原场景所有Actor的材质

使用蓝图方法&#xff1a; 1.修改场景所有Actor 材质&#xff1a; Wirframe&#xff1a;一个材质类 MatList&#xff1a;获取到的所有模型的全部材质 的列表 TempAllClass&#xff1a;场景中所有获取的 Actor 的列表 功能方法如下&#xff1a; 蓝图代码可复制在&#xff1a…

adb命令学习记录

1、 adb ( android debug bridge)安卓调试桥&#xff0c;用于完成电脑和手机之间的通信控制。 xcode来完成对于ios设备的操控&#xff0c;前提是有个mac电脑。 安卓系统是基于linux内核来进行开发的。 2、adb的安装: 本身 adb是 android SDK 其中自带的工具&#xff0c;用于完…

web Speech Synthesis 文字语音播报,Audio 播放base64提示音

SpeechSynthesisUtterance基本介绍 SpeechSynthesisUtterance是HTML5中新增的API,用于将指定文字合成为对应的语音.也包含一些配置项,指定如何去阅读(语言,音量,音调)等 SpeechSynthesisUtterance基本属性 SpeechSynthesisUtterance.lang 获取并设置话语的语言SpeechSynthesisU…

打包CSS

接上一个打包HTML继续进行CSS的打包 1.在之前的文件夹里的src文件夹创建一个css文件 2.在浏览器打开webpack——>中文文档——>指南——>管理资源——>加载CSS 3.复制第一句代码到终端 4.复制下图代码到webpack.config.js脚本的plugins&#xff1a;[.....]内容下…

内存cache大量使用问题导致应用异常问题

概述 28s应用崩溃查看内存使用有大量cache。 分析 查看free 信息平时的确存在大量cache使用的情况查看dmes信息发现filesendserver崩溃 崩溃信息为系统调用 查看到page allocation failure:order 5 同时也看到系统内存使用情况 查看到系统实际还有部分内存为空闲内存&am…

【原创分享】Altium Designer 23全新PCB模块复用方法教程

"Reuse Blocks"功能即“复用块”功能是Altium Designer 23设计环境中的一项强大工具&#xff0c;它允许用户将先前创建的设计模块存储在一个可访问的库中&#xff0c;并在需要时将其插入到新的设计中。通过"Reuse Blocks"&#xff0c;设计师可以节省大量时…