邻接矩阵法

  • 图的邻接矩阵(adjacency matrix)是一种采用邻接矩阵数组表示顶点之间相邻关系的存储结构。设G=(V,E)是含有n(n>0)个顶点的图,各顶点的编号为0~(n-1),则G的邻接矩阵数组A是n阶方阵,其定义如下:

  • 如果G是不带权无向图,则:
    A[i][j]={1若(i,j)∈E(G)0其他A[i][j]=\begin{cases} 1\;\;\;\;若(i,j)∈E(G) \\ 0\;\;\;\;其他 \\ \end{cases} A[i][j]={1若(i,j)∈E(G)0其他​

  • 如果G是不带权有向图,则:
    A[i][j]={1若<i,j>∈E(G)0其他A[i][j]=\begin{cases} 1\;\;\;\;若<i,j>∈E(G) \\ 0\;\;\;\;其他 \\ \end{cases} A[i][j]={1若<i,j>∈E(G)0其他​

  • 如果G是带权无向图,则:
    A[i][j]={wij若i≠j且(i,j)∈E(G),该边的权为wij0i=j∞其他A[i][j]=\begin{cases} w_{ij}\;\;\;\;若i≠j且(i,j)∈E(G),该边的权为w_{ij} \\ 0\;\;\;\;i=j \\ ∞\;\;\;\;其他 \\ \end{cases} A[i][j]=⎩⎪⎨⎪⎧​wij​若i​=j且(i,j)∈E(G),该边的权为wij​0i=j∞其他​

  • 如果G是带权有向图,则:
    A[i][j]={wij若i≠j且<i,j>∈E(G),该边的权为wij0i=j∞其他A[i][j]=\begin{cases} w_{ij}\;\;\;\;若i≠j且<i,j>∈E(G),该边的权为w_{ij} \\ 0\;\;\;\;i=j \\ ∞\;\;\;\;其他 \\ \end{cases} A[i][j]=⎩⎪⎨⎪⎧​wij​若i​=j且<i,j>∈E(G),该边的权为wij​0i=j∞其他​

邻接矩阵类型的声明

#define MaxVertenNum 100 //顶点数目的最大值
typedef char VertexType; //顶点的数据类型
typedef int EdgeType; //存放顶点信息
typedef struct
{VertexType Vex[MaxVertenNum]; //顶点表EdgeType Edge[MaxVertenNum][MaxVertenNum]; //邻接矩阵int vexnum, arcnum; //图的当前顶点数和弧数
}MGraph;

邻接矩阵类型的特点

  1. 图的邻接矩阵表示是唯一的。
  2. 对于含有n个顶点的图,当采用邻接矩阵存储时,无论是有向图还是无向图,也无论边的数目是多少,其存储空间都为O(n2)O(n^2)O(n2),所以邻接矩阵适合于存储边的数目较多的稠密图。
  3. 无向图的邻接矩阵数组一定是一个对称矩阵,因此可以采用压缩存储的思想,在存放邻接矩阵数组时只需存放上(或下)三角部分的元素即可。
  4. 对于无向图,邻接矩阵数组的第i行或第j列非零元素、非∞元素的个数正好是顶点i的度。
  5. 对于有向图,邻接矩阵数组的第i行(或第i列)非零元素、非∞元素的个数正好是顶点i的出度(或入度)。
  6. 在邻接矩阵中,判断图中两个顶点之间是否有边或者求两个顶点之间边的权的执行时间为O(1)。所以在需要提取边权值的算法中通常采用邻接矩阵存储结构。

不带权无向图基本操作的代码实现

#include<stdio.h>
#define MaxVertenNum 100 //顶点数目的最大值
#define NodeNum 6 //顶点个数
typedef char VertexType; //顶点的数据类型
typedef int EdgeType; //存放顶点信息
typedef struct
{VertexType Vex[MaxVertenNum]; //顶点表EdgeType Edge[MaxVertenNum][MaxVertenNum]; //邻接矩阵int vexnum, edgenum; //图的当前顶点数和边数
}MGraph;void InitG(MGraph& g) //初始化
{int i, j;for (i = 0; i < MaxVertenNum; i++) g.Vex[i] = '\0';for (i = 0; i < MaxVertenNum; i++)for (j = 0; j < MaxVertenNum; j++)g.Edge[i][j] = 0;g.vexnum = 0;g.edgenum = 0;
}void CreateVex(MGraph& g) //创建顶点信息
{int i = 0, count = 0;printf("输入图的顶点:");VertexType ch= getchar();while (ch != '#'){g.Vex[i++] = ch;ch = getchar();count++; //统计顶点个数}g.vexnum = count;
}void CreateEdge(MGraph& g) //创建邻接矩阵信息
{EdgeType b;printf("输入邻接矩阵信息:\n");for (int i = 0; i < g.vexnum; i++)for (int j = 0; j < g.vexnum; j++){scanf("%d", &b);g.Edge[i][j] = b;}
}void Info(MGraph& g) //图的顶点数和边数
{int count = 0;for (int i = 0; i < g.vexnum; i++)for (int j = 0; j < g.vexnum; j++)if (g.Edge[i][j] == 1) count++;g.edgenum = count / 2;
}int CountDegree(MGraph g, VertexType point) //统计每个顶点的度
{int j, count = 0;for (int i = 0; i < g.vexnum; i++)if (g.Vex[i] == point) j = i;for (int k = 0; k < g.vexnum; k++) if (g.Edge[j][k] == 1) count++;return count;
}void PrintG(MGraph g) //输出各顶点的连接情况
{int i, j;for (i = 0; i < g.vexnum; i++){for (j = 0; j < g.vexnum; j++)if (g.Edge[i][j] == 1) printf("%c->%c      ", g.Vex[i], g.Vex[j]);printf("\n");}
}bool Adjacent(MGraph g, VertexType x, VertexType y) //判断图G是否存在边(x,y)
{int i, j, k;for (i = 0; i < g.vexnum; i++){if (g.Vex[i] == x) j = i;if (g.Vex[i] == y) k = i;}if (g.Edge[j][k] == 1) return true;else return false;
}void Neighbors(MGraph g, VertexType x) //列出图G中与结点x邻接的边
{int i, j;for (i = 0; i < g.vexnum; i++)if (g.Vex[i] == x) j = i;for (i = 0; i < g.vexnum; i++)if (g.Edge[j][i] == 1)printf("%c ", g.Vex[i]);
}bool InsertVertex(MGraph& g, VertexType x) //在图G中插入顶点x
{for (int i = 0; i < g.vexnum; i++)if (x == g.Vex[i]) return false; //与图G中原有顶点值相同g.Vex[g.vexnum] = x;g.vexnum++;return true;
}bool DeleteVertex(MGraph& g, VertexType x) //从图G中删除顶点x
{int i, j, k;for (i = 0; i < g.vexnum; i++)if (x == g.Vex[i]) k = i;if (k < g.vexnum){for (j = k; j < g.vexnum - 1; j++) //处理顶点表中的值g.Vex[j] = g.Vex[j + 1];//处理邻接矩阵中的值for (i = 0; i < k; i++) //处理矩阵右上元素for (j = k; j < g.vexnum - 1; j++)g.Edge[i][j] = g.Edge[i][j + 1];for (i = k; i < g.vexnum - 1; i++)  //处理矩阵左上元素for (j = 0; j < k; j++)g.Edge[i][j] = g.Edge[i + 1][j];for (i = k; i < g.vexnum - 1; i++)  //处理矩阵右下元素for (j = k; j < g.vexnum - 1; j++)g.Edge[i][j] = g.Edge[i + 1][j + 1];g.vexnum--;return true;}return false;
}void PrintMatrix(MGraph g) //输出邻接矩阵
{int i, j;printf("输出邻接矩阵:\n");for (i = 0; i < g.vexnum; i++)printf("\t%c", g.Vex[i]);printf("\n");for (i = 0; i < g.vexnum; i++){printf("%c", g.Vex[i]);for (j = 0; j < g.vexnum; j++)printf("\t%d", g.Edge[i][j]);printf("\n");}printf("\n");
}bool AddEdge(MGraph& g, VertexType x, VertexType y) //若无向边(x, y)不存在,则向图G中添加该边
{int i, j, k;for (i = 0; i < g.vexnum; i++){if (g.Vex[i] == x) j = i;if (g.Vex[i] == y) k = i;}if (j >= g.vexnum || k >= g.vexnum) return false; //不存在顶点x或顶点yelse{if (g.Edge[j][k] == 0){g.Edge[j][k] = 1;g.Edge[k][j] = 1;return true;}else return false; //该边已存在}
}bool RemoveEdge(MGraph& g, VertexType x, VertexType y) //若无向边(x, y)存在,则在图G中删除该边
{int i, j, k;for (i = 0; i < g.vexnum; i++){if (g.Vex[i] == x) j = i;if (g.Vex[i] == y) k = i;}if (j >= g.vexnum || k >= g.vexnum) return false; //不存在顶点x或顶点yelse{if (g.Edge[j][k] == 1){g.Edge[j][k] = 0;g.Edge[k][j] = 0;return true;}else return false; //该边不存在}
}int FirstNeighbor(MGraph g, VertexType x) //求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1。
{int i, j;for (i = 0; i < g.vexnum; i++)if (x == g.Vex[i]) j = i;if (j >= g.vexnum) return -1; //图中不存在值为x的顶点else{for (i = 0; i < g.vexnum; i++)if (g.Edge[j][i] == 1) return i; //返回顶点号if (i >= g.vexnum) return -1; //x没有邻接点}
}int NextNeighbor(MGraph g, VertexType x, VertexType y)
//假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1
{int i, j, k;for (i = 0; i < g.vexnum; i++){if (g.Vex[i] == x) j = i;if (g.Vex[i] == y) k = i;}if (j >= g.vexnum || k >= g.vexnum) return false; //不存在顶点x或顶点yelse{for (i = k + 1; i < g.vexnum; i++){if (g.Edge[j][i] == 1) return i; //返回顶点号}if (i >= g.vexnum) return -1; //x没有邻接点}
}int main()
{MGraph g;VertexType Vex[MaxVertenNum];EdgeType Edge[MaxVertenNum][MaxVertenNum];InitG(g);CreateVex(g);CreateEdge(g);Info(g);printf("\n无向图G中共有:%d个顶点,%d条边\n", g.vexnum, g.edgenum);PrintMatrix(g);printf("输出无向图G中各顶点的连接情况:\n");PrintG(g);int sumdegree = 0, i;for (i = 0; i < g.vexnum; i++){int degree;degree = CountDegree(g, g.Vex[i]);printf("顶点%c的度为:%d\n", g.Vex[i], degree);sumdegree = sumdegree + degree;}printf("无向图G中所有顶点的度之和为:%d\n", sumdegree);/*VertexType x, y;printf("\n-----判断图G是否存在边(x,y)-----\n");x = 'C', y = 'F';printf("顶点%c和顶点%c之间存在边吗?(1表示存在,0表示不存在)— %d", x, y, Adjacent(g, x, y));x = 'A', y = 'D';printf("\n顶点%c和顶点%c之间存在边吗?(1表示存在,0表示不存在)— %d\n", x, y, Adjacent(g, x, y));*//*printf("\n-----列出图G中与结点x邻接的边-----\n");x = 'B';printf("与顶点%c连接的边有:", x);Neighbors(g, x);printf("\n");*//*printf("\n-----在图G中插入顶点x-----\n");x = 'G';printf("插入顶点%c", x);printf("插入成功了吗?— %d(1表示成功,0表示失败)\n", InsertVertex(g, x));PrintG(g);Info(g);printf("无向图G中共有:%d个顶点,%d条边\n", g.vexnum, g.edgenum);PrintMatrix(g);*//*printf("\n-----在图G中删除顶点x-----\n");x = 'C';printf("删除顶点%c\n", x);printf("删除成功了吗?(1表示成功,0表示失败)— %d\n", DeleteVertex(g, x));printf("输出无向图G中各顶点的连接情况:\n");PrintG(g);printf("\n");Info(g);printf("\n无向图G中共有:%d个顶点,%d条边\n", g.vexnum, g.edgenum);PrintMatrix(g);*//*printf("\n-----图G中添加无向边(x, y)-----\n");x = 'E', y = 'F';printf("在顶点%c与顶点%c之间添加一条无向边\n", x, y);printf("添加成功了吗?— %d(1代表成功,原图中没有边(x, y),0代表失败,原图中已存在该边或者顶点x/顶点y不存在)\n", AddEdge(g, x, y));printf("\n");PrintMatrix(g);printf("输出无向图G中各顶点的连接情况:\n");PrintG(g);printf("\n");*//*printf("\n-----删除图G中无向边(x, y)-----\n");x = 'B', y = 'F';printf("删除(若存在)顶点%c与顶点%c之间的一条无向边\n", x, y);printf("删除成功了吗?— %d(1代表成功,原图中有边(x, y),0代表失败,原图中不存在该边或者顶点x/顶点y不存在)\n", RemoveEdge(g, x, y));printf("\n");PrintMatrix(g);printf("输出无向图G中各顶点的连接情况:\n");PrintG(g);printf("\n");*//*printf("\n-----求图G中顶点x的第一个邻接点-----\n");x = 'E';printf("图G中顶点%c的第一个邻接点的顶点号为:%d(-1代表x没有邻接点或图中不存在x)\n", x,FirstNeighbor(g,x));*//*printf("\n-----求图G中除y之外顶点x的下一个邻接点的顶点号-----\n");x = 'B', y = 'E';printf("图G中除顶点%c之外顶点%c的下一个邻接点的顶点号为:%d(-1代表x没有邻接点或图中不存在x)\n", x, y, NextNeighbor(g, x, y));*/return 0;
}

  • ①Adjacent(G,x,y):判断图G是否存在边(x,y)。
  • ②Neighbors(G,x):列出图G中与结点x邻接的边。
  • ③InsertVertex(G,x):在图G中插入顶点x。
  • ④DeleteVertex(G,x):从图G中删除顶点x。
  • ⑤Addedge(G,x,y):若无向边(x,y)不存在,则向图G中添加该边。
  • ⑥RemoveEdge(G,x,y):若无向边(x,y)存在,则从图G中删除该边。
  • ⑦FirstNeighbor(G,x):求图G中顶点x的第一个邻接点,若有则返回顶点号。若x没有邻接点或图中不存在x,则返回-1。
  • ⑧NextNeighbor(G,x,y):假设图G中顶点y是顶点x的一个邻接点,返回除y外顶点x的下一个邻接点的顶点号,若y是x的最后一个邻接点,则返回-1。

邻接矩阵法的性质

  • 设图G的邻接矩阵为A(矩阵元素为0/1),则AnA^nAn的元素An[i][j]A^n[i][j]An[i][j]等于由顶点i到顶点j的长度为n的路径的数目。

A2[1][1]=1A^2[1][1]=1A2[1][1]=1:表示A-A长度为2的路径有1条,A2[2][2]=3A^2[2][2]=3A2[2][2]=3:表示B-B长度为2的路径有3条,A2[3][3]=2A^2[3][3]=2A2[3][3]=2:表示C-C长度为2的路径有2条…

A3[1][2]=3A^3[1][2]=3A3[1][2]=3:表示A-B长度为3的路径有3条,A3[2][4]=4A^3[2][4]=4A3[2][4]=4表示B-D长度为2的路径有4条,A3[3][1]=1A^3[3][1]=1A3[3][1]=1表示C-A长度为3的路径有1条,A3[4][4]=2A^3[4][4]=2A3[4][4]=2表示D-D长度为2的路径有2条…

数据结构—邻接矩阵存储法代码实现相关推荐

  1. C++ class实现邻接矩阵存储的图(完整代码)

    代码如下: #include <iostream> #include <queue> using namespace std; typedef int VertexType; ...

  2. 数据结构-图-邻接矩阵-试在邻接矩阵存储结构上实现图的基本操作 matrix_insert_vertex 和matrix_insert_arc-icoding

    邻接矩阵 试在邻接矩阵存储结构上实现图的基本操作 matrix_insert_vertex 和matrix_insert_arc,相关定义如下: typedef int VertexType;type ...

  3. 2021秋季《数据结构》_EOJ 1063.树的双亲存储法(parent+child / parent)

    题目 前面介绍了树的链式存储结构,那么如何用顺序存储来存储一棵树呢?在顺序存储时,我们除了存储每个结点值外,还要存储树中结点与结点之间的逻辑关系(即双亲与孩子结点之间的关系).下面介绍树的双亲存储法. ...

  4. 图的邻接矩阵存储(简单代码实现)

    说起来邻接矩阵,对于学过线性代数的同学理解起来非常简单 其实就是一个数字组成方阵,每一个数字都能有有意义的代表一些信息. 下面来看一个例子 如上图所示的图,使用邻接矩阵存储的话应该是下面的情况 由此可 ...

  5. 【图】什么是图?无向图怎么存储?邻接表和邻接矩阵如何用代码存储图?

    目录 一.概念 图是什么 各种图的定义 二.图的存储结构 邻接矩阵 邻接表 三.代码实现图的存储 1.无向图存储 2.邻接矩阵存储图 核心代码 完整代码 3.邻接表存储有向图(不含权重) 核心代码 完 ...

  6. 图的数组(邻接矩阵)存储结构

    图是比较复杂的数据结构,它由顶点和顶点之间的弧或边组成.任何两个顶点之间都 可能存在弧或边.在计算机存储图时,只要能表示出顶点的个数及每个顶点的特征.每对 顶点之间是否存在弧(边)及弧(边)的特征,就 ...

  7. 图的邻接矩阵存储及遍历操作

    第1关:图的邻接矩阵存储及求邻接点操作 任务描述 本关任务:要求从文件输入顶点和边数据,包括顶点信息.边.权值等,编写程序实现以下功能. 1)构造无向网G的邻接矩阵和顶点集,即图的存储结构为邻接矩阵. ...

  8. Java数据结构——邻接矩阵+邻接表

    文章目录 一.邻接矩阵 二.邻接表 一.邻接矩阵 1. 定义 vexs[](存储顶点)和 arcs[][](存储边关系,叫邻接矩阵)集合.因此,用一个一维数组存放图中所有顶点数据: 用一个二维数组存放 ...

  9. pytorch默认初始化_小白学PyTorch | 9 tensor数据结构与存储结构

    [机器学习炼丹术]的学习笔记分享<> 小白学PyTorch | 8 实战之MNIST小试牛刀 小白学PyTorch | 7 最新版本torchvision.transforms常用API翻 ...

最新文章

  1. python中对象及对象引用--傻傻分不清
  2. JVM---堆(对象分配过程)
  3. 找不到_笔记本找不到无线网络怎么办
  4. 天才编程少女16岁获哈佛offer,全民网红时代,我们该怎么做?
  5. centos mysql phpmyadmin_CentOS下phpMyAdmin安装
  6. c语言的链表ppt,C语言链表详解.ppt
  7. kmeans算法中的sse_kmeans算法理解及代码实现
  8. 计算机游戏软件视频,电脑录制游戏视频软件哪个好,电脑游戏录制软件排行
  9. uniapp企业微信第三方网页授权登录获取code
  10. vue 使用qrcode生成二维码功能
  11. C#Skip和Take的用法
  12. 发送短信验证码(天翼开放平台)
  13. 树莓派用GPIO实现模拟交通红绿灯
  14. 解决启动MySql时出现 2003 - Can't connect to MySQL server on '127.0.0.1'(10038)问题
  15. Linux下安装pymysql步骤
  16. 理解微分方程和线性代数的联系
  17. 联想拯救者15isk-i5版加装固态硬盘和内存条
  18. 身为程序员还看不懂UML类图? 一文带你零基础学会看UML类图!
  19. 解决usb otg线系统重启的问题
  20. 员工关系专员岗位职责是什么?什么是员工关系专员?

热门文章

  1. ZLG 开源 GUI 引擎 AWTK 1.6 发布
  2. Linux下安装Redis详细步骤具体教程
  3. Spring之IOC的注入方式总结
  4. Mysql 避免使用 IN 和 NOT IN
  5. qq聊天记录备份与恢复
  6. android 记录血糖的折线图_撼高组血压血糖app下载-撼高组血压血糖安卓版 v1.0.4 - 安下载...
  7. 第十二章:synchronized与锁升级
  8. BUAA 编译作业 练习2-1 2-2 2-3
  9. ASP下使用md5加密注册信息
  10. 谷歌地球 V6.2.1.6014 简体中文版