算法【邻接矩阵、邻接表、链式前向星建图】

一般建图的三种方式

1.邻接矩阵(适合点的数量不多的图)

2.邻接表(最常用的方式)

3.链式前向星(空间要求严苛情况下使用。比赛必用,大厂笔试、面试不常用)

邻接矩阵自是不用多说,邻接表就是每个点后面跟一个存储着从这个点出发的连接的点,如果边带权值,就存储一个数组。下面着重讲解链式前向星建图。

在链式前向星建图中,有3个数组,分别是,head、next、to。head数组,下标为点的编号,一般从1开始,值代表从下标编号的点开始遍历的第一条边的编号,初始化为0,代表还没有边。next数组,下标为边的编号,一般从1开始,值代表遍历完这条边后下一条边的编号,如果为0代表没有了。to数组,下标为边的编号,一般从1开始,值代表这条边指向的点的编号。如果是带权图,那么新加一个weight数组,下标为边的编号,一般从1开始,值代表这条边的权值。当我们得到一条边的信息:出度节点i、入度节点j,这里建不带权图,我们会有一个cnt变量记录当前的边的编号,这时,由出度节点得到head[i],将next[cnt]赋值为head[i],然后把head[i]更新为cnt,最后将to[cnt]赋值为j。如果有权值,将weight[cnt]赋值为权值。最后cnt加1。将所有边更新完,图便建立完成。

下面给出三种建图方法的代码。代码如下。

#include <iostream>
#include <vector>
using namespace std;
// 点和边的数量
int m = 11;
int n = 21;
// 邻接矩阵建图 不带权图
int graph1[12][12];
void build1_1(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        graph1[edges[i][0]][edges[i][1]] = 1;
        // graph1[edges[i][1]][edges[i][0]] = 1;
    }
}
// 邻接矩阵建图 带权图
void build1_2(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        graph1[edges[i][0]][edges[i][1]] = edges[i][2];
        // graph1[edges[i][1]][edges[i][0]] = edges[i][2];
    }
}
// 邻接表建图 不带权图
vector<vector<int>> graph2_1;
void build2_1(vector<vector<int>>& edges){
    vector<int> temp;
    for(int i = 0;i <= m;++i){
        graph2_1.push_back(temp);
    }
    for(int i = 0;i < n;++i){
        graph2_1[edges[i][0]].push_back(edges[i][1]);
        // graph2_1[edges[i][1]].push_back(edges[i][0]);
    }
}
// 邻接表建图 带权图
vector<vector<vector<int>>> graph2_2;
void build2_2(vector<vector<int>>& edges){
    vector<vector<int>> temp1;
    vector<int> temp2;
    for(int i = 0;i <= m;++i){
        graph2_2.push_back(temp1);
    }
    for(int i = 0;i < n;++i){
        temp2.push_back(edges[i][1]);
        temp2.push_back(edges[i][2]);
        graph2_2[edges[i][0]].push_back(temp2);
        temp2.clear();
        // temp2.push_back(edges[i][0]);
        // temp2.push_back(edges[i][2]);
        // graph2_2[edges[i][1]].push_back(temp2);
        // temp2.clear();
    }
}
// 链式前向星建图 不带权图
int Head[12] = {0};
int Next[22] = {0};
int To[22] = {0};
int cnt = 1;
void build3_1(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        Next[cnt] = Head[edges[i][0]];
        Head[edges[i][0]] = cnt;
        To[cnt] = edges[i][1];
        ++cnt;
        // Next[cnt] = Head[edges[i][1]];
        // Head[edges[i][1]] = cnt;
        // To[cnt] = edges[i][0];
        // ++cnt;
    }
}
// 链式前向星建图 带权图
int Weight[22] = {0};
void build3_2(vector<vector<int>>& edges){
    for(int i = 0;i < n;++i){
        Next[cnt] = Head[edges[i][0]];
        Head[edges[i][0]] = cnt;
        To[cnt] = edges[i][1];
        Weight[cnt] = edges[i][2];
        ++cnt;
        // Next[cnt] = Head[edges[i][1]];
        // Head[edges[i][1]] = cnt;
        // To[cnt] = edges[i][0];
        // Weight[cnt] = edges[i][2];
        // ++cnt;
    }
}

其中,点的编号和边的编号都是从1开始;默认建有向图,注释掉的代码是建无向图;m是点的数量,n是边的数量,当然这里这是做一个例子,具体情况具体修改即可。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

还有糕手

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值