首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >从社交圈到代码:一文读懂无向图的邻接矩阵

从社交圈到代码:一文读懂无向图的邻接矩阵

作者头像
fashion
发布2025-12-31 16:52:28
发布2025-12-31 16:52:28
4510
举报

在数据结构的世界里,“图” 是个神奇的存在 —— 它能像地图一样描绘城市间的道路,也能像通讯录一样记录人与人的关联。而今天我们要聊的 “无向邻接矩阵”,就是描述图的 “万能密码本”,哪怕是新手也能轻松 get 它的核心逻辑。

一、先搞懂:什么是 “无向图”?

其实图的概念特别好理解,我们可以把它想象成一个 “社交圈”:

  • 每个 “人” 就是图里的顶点(Vertex),比如你、我、小明、小红;
  • 两个人之间的 “朋友关系” 就是图里的边(Edge)
  • 而 “无向” 的意思更简单 —— 朋友关系是相互的,你把我当朋友,我也把你当朋友,这种双向的关联就叫 “无向边”。

举个具体的例子:如果有 4 个人(0、1、2、3),他们的朋友关系是这样的:0 和 1 是朋友、0 和 2 是朋友、0 和 3 是朋友、1 和 2 是朋友、2 和 3 是朋友。把这些关系画出来,就是一个典型的 “无向图”—— 没有箭头,只靠线条连接彼此。

二、关键来了:用 “邻接矩阵” 记录关系

既然无向图是 “社交圈”,那怎么把这个圈子 “写进代码” 里?答案就是邻接矩阵—— 一个用 “行” 和 “列” 对应顶点,用 “0 和 1” 表示是否有边的表格。

1. 邻接矩阵的核心逻辑

假设我们有 4 个顶点(编号 0-3),邻接矩阵就是一个 4×4 的表格:

  • 行号和列号都代表 “顶点编号”(比如第 0 行对应顶点 0,第 1 列对应顶点 1);
  • 表格里的数字(0 或 1)代表 “边的存在与否”:
    • 若 matrix[i][j] = 1,说明顶点 i 和顶点 j 是朋友(有边相连);
    • 若 matrix[i][j] = 0,说明顶点 i 和顶点 j 不是朋友(无边相连)。

因为是 “无向图”,朋友关系双向,所以邻接矩阵一定是对称的—— 比如 matrix[0][1] = 1,那 matrix[1][0] 也必须是 1,就像 “你是我的朋友,我也是你的朋友” 一样。

2. 用代码定义邻接矩阵

光说理论不够,我们直接看 C 语言的实现(这也是最直观的理解方式)。首先要定义一个 “图的结构体”,把顶点、邻接矩阵、顶点数、边数都装进去:

代码语言:txt
复制
#include<stdio.h>
// 定义顶点类型(这里用字符表示顶点编号,比如'0'、'1')
typedef char vertaxType; 
// 定义边的类型(0表示无边,1表示有边)
typedef int edgeType; 
// 最大顶点数(可根据需求调整)
#define maxsize 100 图的邻接矩阵结构体
typedef struct mat_grph {
vertaxType ver[maxsize]; / 存储所有顶点
edgeType arc[maxsize][maxsize];// 邻接矩阵(核心!)
int ver_num; 际顶点个数
int arc_num; / 实际边的个数
} mat_grph; 结构体命名为mat_grph // / // 实 / 
//

这个结构体就像一个 “图的工具箱”:ver数组存顶点名字,arc二维数组就是邻接矩阵,ver_num和arc_num则记录图的大小。

三、动手实现:初始化 + 打印邻接矩阵

知道了结构,我们就来 “搭建” 一个具体的无向图 —— 还是用之前的 4 人社交圈举例。

1. 初始化邻接矩阵

初始化的核心是两步:先把矩阵 “清空”(全设为 0),再根据实际关系 “填 1”。

代码语言:txt
复制
// 初始化图
void init_grph(mat_grph* G) {
// 1. 设置顶点数和边数(4个顶点,5条边)
G->ver_num = 4;
G->arc_num = 5;
// 2. 给顶点命名(这里直接用'0'~'3')
G->ver[0] = '0';
G->ver[1] = '1';
G->ver[2] = '2';
G->ver[3] = '3';
// 3. 初始化邻接矩阵:先全设为0(默认无边)
for (int i = 0; i < G->ver_num; i++) {
for (int j = 0; j < G->ver_num; j++) {
G->arc[i][j] = 0;
}
}
// 4. 填充边(无向图要对称赋值!)
G->arc[0][1] = 1; G->arc[1][0] = 1; // 0和1是朋友
G->arc[0][2] = 1; G->arc[2][0] = 1; // 0和2是朋友
G->arc[0][3] = 1; G->arc[3][0] = 1; // 0和3是朋友
G->arc[1][2] = 1; G->arc[2][1] = 1; // 1和2是朋友
G->arc[2][3] = 1; G->arc[3][2] = 1; // 2和3是朋友
}

这里一定要注意 “对称赋值”—— 比如给arc[0][1]设 1 后,必须给arc[1][0]也设 1,否则就变成 “单向关系”(有向图)了,不符合我们的无向图需求。

2. 打印邻接矩阵:看结果更直观

初始化后,我们可以写一个函数把邻接矩阵打印出来,看看是不是符合预期:

代码语言:txt
复制
// 输出邻接矩阵
void print_grph(mat_grph G) {
printf("无向图的邻接矩阵:\n");
for (int i = 0; i < G.ver_num; i++) {
for (int j = 0; j < G.ver_num; j++) {
printf("%4d", G.arc[i][j]); // 每个元素占4位,排版更整齐
}
printf("\n"); // 每行结束换行
}
}

3. 主函数调用:跑起来看看

最后写个主函数,把前面的功能串起来:

代码语言:txt
复制
int main() {
mat_grph G; 图的结构体变量
init_grph(&G); // 初始化图(传地址,修改结构体内容)
print_grph(G); // 打印邻接矩阵
return 0;
} // 创建

运行结果会是这样的(注意看对称性!):

代码语言:txt
复制
无向图的邻接矩阵:
0 1 1 1
1 0 1 0
1 1 0 1
1 0 1 0

对比我们之前的 “社交圈”,这个矩阵完美记录了所有朋友关系 —— 比如第 0 行有 3 个 1,说明顶点 0 和 1、2、3 都是朋友,完全正确!

四、为什么要用无向邻接矩阵?

可能有人会问:记录关系的方式有很多,为啥偏偏选邻接矩阵?它的优势很明显:

  1. 查询快:想知道两个顶点有没有边?直接看arc[i][j]的值,一步到位,时间复杂度是 O (1);
  2. 实现简单:用二维数组就能表示,代码逻辑清晰,新手也能快速上手;
  3. 对称性直观:无向图的双向关系通过矩阵对称直接体现,不用额外记录方向。

当然,它也有小缺点 —— 如果顶点多但边少(比如 1000 个人,只有 10 对朋友),邻接矩阵会有很多 0,浪费内存。但对于边比较多的 “稠密图”,它绝对是首选。

五、总结:无向邻接矩阵的核心

其实看完这么多,你会发现无向邻接矩阵一点都不复杂:

  • 本质是 “用表格记录关系”,行和列对应顶点,值对应边;
  • 无向图的关键是 “对称赋值”,体现双向关系;
  • 代码实现围绕 “结构体定义→初始化→打印” 三步,逻辑清晰。

下次再看到 “图” 的问题,不妨先想想:如果用邻接矩阵来表示,这个 “社交圈” 会是什么样的表格?跟着这个思路走,数据结构的很多难题都会变得简单~

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2025-12-31,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、先搞懂:什么是 “无向图”?
  • 二、关键来了:用 “邻接矩阵” 记录关系
    • 1. 邻接矩阵的核心逻辑
    • 2. 用代码定义邻接矩阵
  • 三、动手实现:初始化 + 打印邻接矩阵
    • 1. 初始化邻接矩阵
    • 2. 打印邻接矩阵:看结果更直观
    • 3. 主函数调用:跑起来看看
  • 四、为什么要用无向邻接矩阵?
  • 五、总结:无向邻接矩阵的核心
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档