图论系列:图的存储

        本人最近学习了图论的基础知识,做了几道入门题目,慢慢的从图论的创建、存储过渡到图的遍历,求图的单源最短路径、拓扑排序。

本次先介绍几种存储图的信息的方法

图的存储

1.邻接表存储

        假设我们现在有一个图里面有n个点,m条边,要利用数组存储的话,我们需要定义一个n*n的二维数组,int edge[n+1][n+1],因为数组下标从0开始,为了方便处理边的信息多定义一行一列

假设图中有以上信息,我们要利用邻接矩阵存储

edge[1][2]=1;
edge[2][3]=1;//有向边


edge[1][2]=1;
edge[2][1]=1;
edge[2][3]=1;
edge[3][2]=1;//无向边,一条边需要双向存储

         图中有节点1指向节点2的边和节点2到节点3的边,它们都是有向的,如果是无向的边,还需要给对称的变量赋值为1代表存在该边。

        通过这样处理,图中的信息就被存储下来了,二维数组的行列下标分别表示起始点和终止点,对应的变量存储一表示存在该边,为0表示不存在。

        如果是带权的图的存储,将上述存储中的1替换成相应的权值即可,同样通过对应下标变量是否为0来判断是否存在改变,非0变量的值就是这个边的权值。

例如上图信息,利用邻接矩阵存储代码如下:

edge[1][2]=2;
edge[2][3]=3;

 这种方式存储图是不是觉得很简单?要查询某一条边是否存在只需要看相应的二维数组变量是不是为0,查询效率为O(1),但是一个东西有利就一定会有弊,想上图中的势力,我们要用邻接矩阵存储就需要定义一个大小为4*4二维数组(下标为0的不用),然而要存储边的信息我们只用到了两个内存单元,这就浪费了大量的内存空间,属于是以空间换时间了。

2.C++ vector存储

        在上面我们知道了利用数组存储图有时候会造成大量的空间浪费,恰好在C++中引入了向量这一类容器,它会随着你放入的内容自动适配存储空间,我们可以利用它来代替二维数组,下面介绍用法

在二维数组中,我们是利用数组下标直接对应点和点的关系,例如edge[1][2]就存储着点1和点2的关系,这里我们定义一个 vector<int> 数组,根据图中点的数量确定数组的大小,每个数组存储对应下标的邻接点的信息,下面给出示例

我们该如何利用vector存储上述图的信息呢?

首先一共四个点,定义大小为4的vector<int> 数组

vector<int> edge[5];//这里默认下标为0的空间不使用

//下标为i的向量中存储与i相连的点
//向量i中每个变量x都代表一条i到x的边

//图中有以下边
//1->3  3->2 3->4

edge[1].push_back(3);
edge[3].push_back(2);
edge[3].push_back(4);

这样,整个向量数组所占空间大小就是3*sizeof(int)个数组

edge中实际只存储如上信息,edge[2]和edge[4]中由于没有内容,系统没有给分配内存,这样只占用有限的空间就存储好了一个图的信息。

那么如果我要查询与节点2相连的节点分别是哪些怎么找呢?代码如下:

vector<int> loca;//存储与结点2相连的点

for(int i=0;i<edge[2].size();i++)
{
    loca.push_back(edge[2][i]);
}

利用如上代码就可以查找一个点所相连的所有节点。

上面是无权边,那么有权的边利用这个方法该怎么存呢?

这个时候我们就需要新定义一个向量数组,与存储边的方式类似,我们存储权实际上就是复刻一个edge向量数组,然后在每一个终点对应的位置替换成相应的边的权值。

来个简单的,图中有1,2这两个点 一个节点1指向节点2的边,权值为5

vector<int> edge[3];//存储边
vector<int> wi[3];//存储权值

edge[1].push_back(2);//将边的信息存入edge

wi[1].push_back(5);//将权值存入对应的wi向量数组中的位置

总结

        总的来说,图的存储,如果这个图是稠密图的话,就可以选择邻接矩阵存储,这样简单粗暴,用起来也简单

        如果不确定边的数量,我们就可以选用vector存储,这样不会超内存,除了本章介绍的两种方式以外还有很多存储图的方式,这两种比较适合新手入门使用,慢慢的熟练之后就可以选择其他的方式。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值