邻接矩阵的定义和实现

邻接矩阵

邻接矩阵的定义

邻接矩阵(Adjacency Matrix)是表示顶点之间相邻关系的矩阵。设G=(V,E)是一个图,其中V={v1,v2,…,vn} [1]  。G的邻接矩阵是一个具有下列性质的n阶方阵:

①对无向图而言,邻接矩阵一定是对称的,而且主对角线一定为零(在此仅讨论无向简单图),副对角线不一定为0,有向图则不一定如此。

②在无向图中,任一顶点i的度为第i列(或第i行)所有非零元素的个数,在有向图中顶点i的出度为第i行所有非零元素的个数,而入度为第i列所有非零元素的个数。

③用邻接矩阵法表示图共需要n^2个空间,由于无向图的邻接矩阵一定具有对称关系,所以扣除对角线为零外,仅需要存储上三角形或下三角形的数据即可,因此仅需要n(n-1)/2个空间。

*以上摘自百度百科

说点人话吧。。。。。。 

简单来说,就是相邻两个点之间都有连接的矩阵(图)就叫做邻接矩阵。

邻接矩阵的实现

*如果还没有看过图的储存那一篇博客请前往那里学习一下图的读入,因为此程序需要在那个程序上进行运行。

图的定义,读入与储存↓

图的定义、读入与储存_dyx916_的博客-CSDN博客

首先,邻接矩阵中可以实现的功能是查找某一点和某一点之间的联系某一点和哪些点有联系

我们先来举个例子(下面的程序就根据这个例子来实现):

 比如这张G1(无向图),我们的目标是查找点1和哪些点有联系(边上的数值表示两点之间的距离)。

首先,我们先要储存两点之间距离的值。

我们可以用一个表格来存储两点之间的值,里面的值表示(行,列)两点之间的距离。

比如(1,2)就是点1到点2的距离。

如果两点之间没有连接,我们可以用一个INF来表示没有连接。

如果两点相同,距离为0。

根据G1,我们把数值填入表格:

1234
10148
21064
3460INF
484INF0

不难发现,无向图中两边数值都是对称的,而有向图则没有这个特点。

而程序中,我们只需开一个二维数组即可,就像这样(vertex为点的数量):

int adj[vertex+1][vertex+1];//为了方便,角标从1开始,所以要比点的数量多一格。

 先将整个二维数组初始化为memset值为20的数组,也就是336860180。

初始化如下:

memset(adj,20,sizeof(adj));//初始化

这个值可以正好作为INF的值,所以如下:

const int INF = 336860180;

 也可以用define来保存这个值,如下:

#define INF 336860180

初始化完成后,我们可以先在读入的循环内加入一些代码,比如如果两个点u、v之间有联系,那么这个二维数组[u][v]和[v][u]的值也正好为边的长度w。

此外,我们还要把[u][u]和[v][v]两个相同的点距离初始化为0,就像这样:

adj[u][v]=w;
adj[v][w]=w;
adj[u][u]=0;
adj[v][v]=0;

存完adj这个数组的值之后,接下来就是读入整个图了。

详情请去上一篇博客(如果提醒了还没去的话

最后,收尾工作就是输出和点1有关的点了。

我们先使用循环来遍历整个[1]为行的值(列不用是因为两边对称),使用if来判断二维数组adj[1][i]中的值不等于INF并且>=1(筛掉无连接和自己本身)并使用printf进行输出即可。如下:

for(int i=1;i<=vertex+1;i++)//因为角标从1开始所以点数要加一
{
    if(adj[1][i]>=1&&adj[1][i]!=INF)
    printf("&d is connect with %d\n",1,i);
}

这样,就算整个代码就完成了。

最后给大家献上完整代码(部分为上次内容):

#include<bits/stdc++.h>
//邻接矩阵
#define INF 336860180
using namespace std;
const int vertex=4;//点的数量
int adj[vertex+1][vertex+1];//存距离的二维数组
const int edge=vertex*(vertex-1);//边的数量 有向就/2
int v[vertex];//点集合 v[i]=j表示第i个节点编号是j
struct edges//边
{
    int from;//该条边的左顶点
    int to;//该条边的右顶点
    double w;//边的长度
};
edges e[edge+1];//边集合
int cnt=1;//当前在读入第cnt条边
void add(int u/*起点*/,int v/*终点*/,int w/*长度*/){
    e[cnt].from=u;//记录第cnt条边的左顶点是u
    e[cnt].to=v;//记录第cnt条边的右顶点是v
    e[cnt].w=w;//记录第cnt条边的长度
    cnt++;//换下一条边去读
}
int main()
{
    memset(adj,20,sizeof(adj));//初始化
    for(int i=1;i<=vertex+1;i++)//读入
    {
        int u,v,w;// 左顶点 右顶点 长度
        cin>>u>>v>>w;
        adj[u][v]=w;//赋值好距离
        adj[v][w]=w;
        adj[u][u]=0;
        adj[v][v]=0;
        add(u,v,w);//单向只需这个
        add(v,u,w);//双向
    }
    for(int i=1;i<=vertex+1;i++)//输出
    {
        if(adj[1][i]>=1&&adj[1][i]!=INF)
        printf("%d is connect with %d\n",1,i);
    }
}

对了,给一个G1的测试数据

1 2 1
1 3 4
1 4 8
2 3 6
2 4 4

输出结果:

 这篇博客就到这里了~

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值