C语言实现邻接矩阵(无向图的顺序表示)

2023-11-05

有向/无向不带权图

在这里插入图片描述

带权图

在这里插入图片描述

定义图的结构体

在这里插入图片描述

#define Default_Vertex_Size  10

#define T char

typedef struct GraphMtx
{
	int MaxVertices;//最大顶点容量
	int NumVertices;//图中顶点个数
	int NumEdges;//图中边的条数

	T   *VerticesList;//指向存有顶点的空间的指针
	int **Edge;//指向存矩阵的空间的指针
}GraphMtx;

初始化

void InitGraph(GraphMtx *g)
{
	g->MaxVertices = Default_Vertex_Size;
	g->NumVertices = g->NumEdges = 0;

//为存储顶点的空间进行初始化
	g->VerticesList = (T*)malloc(sizeof(T)*(g->MaxVertices));
	assert(g->VerticesList != NULL);

//为存储矩阵的空间进行初始化
	g->Edge = (int**)malloc(sizeof(int*) * g->MaxVertices);
	assert(g->Edge != NULL);
	for(int i=0; i<g->MaxVertices; ++i)
	{
		g->Edge[i] = (int*)malloc(sizeof(int) * g->MaxVertices);
	}
	for(i=0; i<g->MaxVertices; ++i)
	{
		for(int j=0; j<g->MaxVertices; ++j)
		{
			g->Edge[i][j] = 0;
		}
	}
}

分析

分配堆空间

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
1F0E90~1F0EB8一共40字节
在这里插入图片描述

对矩阵的行开辟空间

在这里插入图片描述
发现了每个行的地址是连续,但是行存储的地址之间相差了104(10进制)
在这里插入图片描述

对矩阵(即二维数组)进行初始化

edge[0][0]-edge[0][9]

在这里插入图片描述在这里插入图片描述

edge[1][0]~edge[1][9]

在这里插入图片描述

edge[2][0]~edge[2][9]

在这里插入图片描述
从这里就可以知道为什么要用int ** 去定义edge。想要获得矩阵里的值,就要先去取edge[i]行里面存的地址,找到那一行的所在列,再根据列的地址找到存储的那个值。

基本操作(根据第一张图进行测试)

void main()
{
	GraphMtx gm;
	InitGraph(&gm);
	InsertVertex(&gm,'A');
	InsertVertex(&gm,'B');
	InsertVertex(&gm,'C');
	InsertVertex(&gm,'D');
	InsertVertex(&gm,'E');

	InsertEdge(&gm,'A','B');
	InsertEdge(&gm,'A','D');
	InsertEdge(&gm,'B','C');
	InsertEdge(&gm,'B','E');
	InsertEdge(&gm,'C','E');
	InsertEdge(&gm,'C','D');
	ShowGraph(&gm);
	//int p = GetFirstNeighbor(&gm,'D');
	int p = GetNextNeighbor(&gm,'D','C');
}

插入顶点

void InsertVertex(GraphMtx *g, T v)
{
	if(g->NumVertices >= g->MaxVertices)
		return;
	g->VerticesList[g->NumVertices++] = v;
}

在这里插入图片描述
插入完毕
在这里插入图片描述

插入边

思路是获取矩阵的行列,如果顶点A和顶点B相连,首先找到A的位置和B的位置;矩阵[A][B]=[B][A]=1

//获取顶点在连续内存(看做数组)中的的位置
int  GetVertexPos(GraphMtx *g, T v)
{
	for(int i=0; i<g->NumVertices; ++i)
	{
		if(g->VerticesList[i] == v)
			return i;
	}
	return -1;
}


//插入边
void InsertEdge(GraphMtx *g, T v1, T v2)
{
	int p1 = GetVertexPos(g,v1);
	int p2 =  GetVertexPos(g,v2);
	if(p1==-1 || p2==-1)
		return;

	if(g->Edge[p1][p2] != 0)
		return;

	g->Edge[p1][p2] = g->Edge[p2][p1] = 1;
	g->NumEdges++;
}

找到A的位置是0,B的位置是1
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

删除边

找到边对应的位置,把矩阵的行列设为0

void RemoveEdge(GraphMtx *g, T v1, T v2)
{
	int p1 = GetVertexPos(g,v1);
	int p2 =  GetVertexPos(g,v2);
	if(p1==-1 || p2==-1)
		return;

	if(g->Edge[p1][p2] == 0)
		return;

	g->Edge[p1][p2] = g->Edge[p2][1] = 0;
	g->NumEdges--;
}

删除顶点(较复杂)

不仅要删除顶点,还要删除相关联的边。这里采用类似顺序表的删除方法

void RemoveVertex(GraphMtx *g, T v)
{
	int p = GetVertexPos(g,v);
	if(p == -1)
		return;

	int numedges = 0;

	for(int i=p; i<g->NumVertices-1; ++i)
	{
		g->VerticesList[i] = g->VerticesList[i+1];//假设删除C,在顶点表中让D给C赋值,E给D赋值
	}

	for(i=0; i<g->NumVertices; ++i)
	{
		if(g->Edge[p][i] != 0)
		{
			numedges++;
		}
	}

	for(i=p; i<g->NumVertices-1; ++i)
	{
		for(int j=0; j<g->NumVertices; ++j)
		{
			g->Edge[i][j] = g->Edge[i+1][j];//让删除顶点所在位置的下一行的列给上一行的列赋值
		}
	}

	for(i=p; i<g->NumVertices; ++i)
	{
		for(int j=0; j<g->NumVertices; ++j)
		{
			g->Edge[j][i] = g->Edge[j][i+1];//让删除顶点所在位置的下一列的行给前一列赋值
		}
	}
	g->NumVertices--;
	g->NumEdges -= numedges;
}

如图所示v1-V5表示A-E
在这里插入图片描述
在这里插入图片描述

也可以直接拿最后一个顶点覆盖要删除的顶点,这样效率更高。

销毁图

void DestroyGraph(GraphMtx *g)
{
	free(g->VerticesList);
	g->VerticesList = NULL;
	for(int i=0; i<g->NumVertices; ++i)
	{
		free(g->Edge[i]);
	}
	free(g->Edge);
	g->Edge = NULL;
	g->MaxVertices = g->NumEdges = g->NumVertices = 0;
}

求一个顶点的第一个邻接顶点

int  GetFirstNeighbor(GraphMtx *g, T v)
{
	int p = GetVertexPos(g,v);
	if(p == -1)
		return -1;

	for(int i=0; i<g->NumVertices; ++i)
	{
		if(g->Edge[p][i] == 1)
			return i;
	}
	return -1;
}

求一个顶点的邻接顶点的下一个顶点

int  GetNextNeighbor(GraphMtx *g, T v, T w)
{
	int pv = GetVertexPos(g,v);//先定位行
	int pw = GetVertexPos(g,w);//从pw+1开始遍历,再定位列
	if(pv==-1 || pw==-1)
		return -1;

	for(int i=pw+1; i<g->NumVertices; ++i)
	{
		if(g->Edge[pv][i] == 1)
			return i;
	}
	return -1;
}

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

C语言实现邻接矩阵(无向图的顺序表示) 的相关文章

  • vs code配置C/C++开发环境

    第一步 下载 Vs Code 点击链接下载Vs Code 下载版本 并安装 https code visualstudio com 点击 Download for Windwos 安装时 如图 请一定要勾选 添加到PATH 环境变量 其他选
  • css文字覆盖线性渐变,利用css使文字渐变

    mark c 本博客加入QQ群就是这个效果 代码来至 青找博客英文名 Qing Zhao mark c 效果图 HTML 一个人真正优秀的特质来自于内心想要变得更加优秀的那种强烈的渴望 和对生命的追求那种火热的激情 CSS masked p
  • 【docker】docker部署tomcat

    目录 1 1 搜索tomcat镜像 1 2 拉取tomcat镜像 1 3 创建容器 设置端口映射 目录映射 1 4 测试 1 1 搜索tomcat镜像 docker search tomcat 1 2 拉取tomcat镜像 docker p

随机推荐

  • Python开发是面向过程、函数还是对象?

    Python虽然是解释型语言 但从设计之初就已经是一门面向对象的语言 对于Python来说一切皆为对象 正因为如此 在Python中创建一个类和对象是很容易的 当然如果习惯面向过程或者函数的写法也是可以的 Python并不做硬性的限制 Py
  • 图像构成与信号处理之三——图像滤波

    一 什么是图像滤波 图像滤波是一种常见的图像处理技术 用于平滑图像 去除噪声和边缘检测等任务 其工作的原理是通过提前设定滤波器 将滤波器作用与原图像 得到拥有需要的滤波效果的图像 一般图像滤波分为平滑类 均值滤波 去噪类 中值滤波 突出边缘
  • 多机器人仓储巡逻路径规划问题的A*算法实现(附带MATLAB代码)

    多机器人仓储巡逻路径规划问题的A 算法实现 附带MATLAB代码 路径规划是多机器人系统中一个重要的问题 特别是在仓储巡逻等应用中 A A Star 算法是一种经典的启发式搜索算法 可以用于解决路径规划问题 本文将介绍如何使用A 算法实现多
  • R手册(Time Series)--forecast and prophet

    文章目录 forecast for Time Series and Linear Models 时间序列分析 模型 预测 ggplot2扩展 模型评估 prophet 构建模型 模型预测 可视化 交叉验证 时间序列分析 Time Serie
  • FPGA面试题

    面试题摘自尤老师FPGA 1 2 TPLH 脉冲由低电平变成高电平的延迟时间 TPHL 脉冲由高电平变成低电平的延迟时间 本题采用假设法 假设开始输入信号为高电平 经过两次非门是一个时钟周期 TPHL TPLH 0 2 ns 震荡周期意思为
  • 今日分享:这4款音频降噪去杂音的软件,太好用了

    你知道音频降噪去杂音怎么操作吗 在现代社会 音频处理已经成为了一项重要的技能 无论是语音录音 音乐创作 还是影视制作 我们都需要高质量的音频素材 但在实际操作中 我们常常会遇到环境噪声 背景杂音等问题 这些问题会导致我们的音频质量下降 影响
  • 使用Ajax加载数据的dataTables

    dataTables是一种很好用前端表格显示库 当加载大量数据时 可以用Ajax 获取数据来提高效率 增速网页加载速率 下面以一个例子作示范 首先 需要下载jquery以及dataTables库 这里使用的是版本是jQuery v1 11
  • 206. Reverse Linked List

    Definition for singly linked list struct ListNode int val ListNode next ListNode int x val x next NULL class Solution pu
  • Ansys workbench分析应用基础(6)

    圣维南原理和模型简化 如上图所示 我们对长度分别为100mm 150mm和200mm的板子添加完全均布载荷 二分之一均布载荷和线载荷 载荷的值相同 统计出不同模型不同情况所对应的应力最大值 如下图所示 从图中 我们可以看出对于板长为200m
  • 2023年5月份中国电子学会青少年软件编程(C语言)等级考试一级真题讲解

    1 输出第二个整数 题目描述 输入三个整数 把第二个输入的整数输出 输入 只有一行 共三个整数 整数之间由一个空格分隔 整数是32位有符号整数 输出 只有一行 一个整数 即输入的第二个整数 样例输入 123 456 789 样例输出 456
  • jsonp原理详解

    JSONP 全称 JSON with padding 是一种跨域请求的方法 它允许在不受限制地从一个域名获取数据并在另一个域名下使用该数据 JSONP 的原理是通过动态创建 script 标签来实现 在客户端向服务器发送请求时 服务器返回
  • 面试宝典----数据库(总结来自知乎路人甲)

    一 什么是存储过程 有哪些优缺点 存储过程是一些预编译的SQL语句 更加直白的理解 存储过程可以说是一个记录集 它是由一些T SQL语句组成的代码块 这些T SQL语句代码像一个方法一样实现一些功能 对单表或多表的增删改查 然后再给这个代码
  • svn 打patch

    patch patch 即 补丁 的意思 当代码有改动的时候 svn会产生diff 可以查看diff和打patch 使用Mac终端来打patch也是非常方便的 首先查看本地的修改 确认无误后 使用 svn diff gt PATCH 命令可
  • C++ main函数中参数argc和argv含义及用法

    argc 是 argument count的缩写 表示传入main函数的参数个数 argv 是 argument vector的缩写 表示传入main函数的参数序列或指针 并且第一个参数argv 0 一定是程序的名称 并且包含了程序所在的完
  • 2022美赛C题思路分享

    美赛c题 比特币和金子投资分析 问题翻译 下附思路 1 问题分析 本题题目理解较为简单 就是利用历史数据对于投资策略的分析 每一天的决策只能使用之前的历史数据 求解最佳的投资回报 并分析模型的可行性 2模型准备 时间序列分析模型选择 以及模
  • 学习实践-Whisper语音识别模型实战(部署+运行)

    1 Whisper内容简单介绍 OpenAI的语音识别模型Whisper Whisper 是一个自动语音识别 ASR Automatic Speech Recognition 系统 OpenAI 通过从网络上收集了 68 万小时的多语言 9
  • 【matplotlib】饼图+legend()、loc、color位置颜色图例中文显示(一个饼图的例子)

    博客已经搬家到 捕获完成 https www v2python com 1 原来自己做的饼图 http mp blog csdn net postedit 79222127 见文章 matplotlib 中文显示 负号显示 统计微信好友性别
  • 《再也不怕elasticsearch》Spring Boot集成Elasticsearch

    大家好我是迷途 一个在互联网行业 摸爬滚打的学子 热爱学习 热爱代码 热爱技术 热爱互联网的一切 再也不怕elasticsearch系列 帅途会慢慢由浅入深 为大家剖析一遍 各位大佬请放心 虽然这个系列帅途有时候更新的有点慢 但是绝对不会烂
  • django获取某一个字段的列表,values/values_list/flat

    django获取某一个字段的列表 values values list flat 2017年11月01日 11 43 28 阅读数 2241 python view plain copy class Building models Mode
  • C语言实现邻接矩阵(无向图的顺序表示)

    文章目录 有向 无向不带权图 带权图 定义图的结构体 初始化 分析 分配堆空间 对矩阵的行开辟空间 对矩阵 即二维数组 进行初始化 edge 0 0 edge 0 9 edge 1 0 edge 1 9 edge 2 0 edge 2 9