邻接表和邻接矩阵的实现与选择

领接表和邻接矩阵的选择;

在我们做到有关图一类的问题时,当需要将一个图的内容存储下来的话一般有两种选择,一种是领接表【一般用(静态)链表来实现】,或者是领接矩形。
而选择时,一般将图分为两种图,这三种种图分别对应两种不同的存储图的方式;

楼主知识比较浅薄,整合知识有不够详细的还请见谅,欢迎大家来补充或者修改

各位小伙伴们大家好,在这里给大家拜年啦

在这里插入图片描述

这里提一下邻接矩阵和邻接表的区别;

邻接矩阵
邻接矩阵在使用时要将所有点初始化,将非自环(自己指向自己的边)初始化为正无穷,自环初始化为0即可这里是为了方便操作
邻接矩阵是将矩阵的纵坐标对应每一个点,比如x = 1 时对应的是点 n = 1;
而 矩阵中 如果 [x][y] = 1的话 ,就表示点 x可以通向 y的边, 同理 [y][x] = 1表示点 y 有通向 x的 边; 值得注意的是,矩阵中的横坐标严格对应起始点,纵坐标严格对应结束点 ,这样当要保存的边是有向边(只能从x点到y点) 这样就只需要将邻接矩阵中的 [x][y] = 1即可, 这里的 1 可以表示为边权(边权就是这一条边的值) .
同理如果要存储无向边(这条路线既可以从x到y也可以从y到x)就需要 将[x][y] = 1 , [y][x] = 1 ,就是存储两条边;
就好像这个图一样 这个图就是用邻接矩阵来存储的,注意这是一个无向图
可以看到每一条边对应的[x][y] 与[y][x]的值都是1 ;
当x == y 时矩阵的边是零,就是表明该点到自己的距离是0
在这里插入图片描述
邻接矩阵的优点是存图时操作方便,缺点是他特别的占空间
邻接表
领接表是将一个点可以指向的点存起来 ,可以用vector来存也或者可以用单单链表来存储,这里就直接用vector来存储了(个人习惯用链表来存)
比如说上方这个图在这里插入图片描述

vector<int> a[6];
a[1] = {2,3,5};
a[2] = {1,4};
a[3] = {1,5};
a[4] = {2};
a[5] = {1,3};

这样就可以将这个图保存下来了,好处是操作容易,不用初始化,坏处是写起来会比较麻烦注意这里是无相图,相当于存储了两条方向相反但位置相同的边

接下里我们来区分使用的时候

第一类 即数据量极小
比如 n为 图中点的个数 ,m为图中边的个数,如果 n 和m 都是小于 50(这里50指的是小数据)的话,无论你选择邻接表还是邻接矩阵的话都是可以解决问题的 就好像是图的遍历类型的dfs 或者bfs都是可以随意选着图的存储方式(记得选自己熟练的嘿嘿)

第二类 边的数据范围远远超过点的数据范围
比如 n 为图中点的个数 , m为图中边的数量,一般当 m的数据范围>=n*n的时候我们认为这种图称为疏密图 , 因为边的数量大于 n的平方,所以很可能会存在两个点会有重复的边,但边权(这里可以理解为路费)可能不一样,这时候我们可以用邻接矩阵来存储这个图,并且在存储图的过程中只保留路费的最小值,这样就可以很好的解决重边的问题;
在这里插入图片描述
像这种图就只能用邻接矩阵来存储了
存储时可以这样存 , 这里省去了初始化;

cin >> n >> m ;
    while(m--)
    {
        int a, b,c;
        cin >> a >> b >>c;
        g[a][b] = min(g[a][b],c);
    }

第三类,点的数量远远超过边的数量
老样子,我们将 n表示点的数量,m表示边的数量。 当 n的数据范围 >= m*m的数据范围时 我们将这种图称为稀疏图,这种图如果用邻接矩阵来存的话,所用的空间很可能会直接爆栈(一种内存太大而使程序直接终止的说法),所以这种时候就可以用邻接表来存储了
比方说这个数据在这里插入图片描述
这个数据当中如果直接用邻接表的话会很难受
所以这里我们用领接表来存储数据
这里我用单链表来存储图

int h[N] , ne[N] , e[N] ,w[N] ,idx;
int n , m;
int dist[N] ,  cnt[N];
bool st[N];
void insert(int a , int b , int c)
{
    e[idx] = b;
    w[idx] = c;
    ne[idx] = h[a];
    h[a] = idx ++ ;
}
int main()
{
    cin >>n >> m ;
    memset(h,-1,sizeof h);
    while(m--)
    {
        int a ,b ,c;
        scanf(" %d%d%d",&a,&b,&c);
        insert(a,b,c);
    }

这里用到的是单链表来存储数据,链表的插入用的是头查法,h可以看做是不存值的头结点,e是每一个节点的值,ne是当前结点指向的下一个结点的值,
idx在存储数据时当做指针使用;
具体的可以参考静态数组的实现;

最后祝大家 新的一年里 皮肤越来越好, 智商越来越来越高, 成绩越来越好, rank分越来越高,运气爆棚 ,一夜暴富,声名鹊起,一飞冲天 O(∩_∩)O哈哈~

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值