图的存储

邻接矩阵

原理

使用一个二维数组 mat 来存边,其中 mat[u][v] = w 表示结点 \(u,v\) 间存在一条权值为 \(w\) 的边

复杂度

设图有 \(n\) 个点 \(m\) 条边

  • 查询是否存在某条边 \(O(1)\)
  • 遍历一个点的所有出边 \(O(n)\)
  • 遍历全图 \(O(n^2)\)
  • 空间复杂度 \(O(n^2)\)
优点与缺点
  • 简易且可以在 \(O(1)\) 的时间里查询一条边是否存在
  • 空间复杂度高,只适合于稠密图
代码
#include<bits/stdc++.h>
using namespace std;

const int MAX_N = 1000 + 5;
int n, m;
int mat[MAX_N][MAX_N];

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        mat[u][v] = mat[v][u] = w;
    }
    return 0;
}

邻接表

原理

使用 vector<int> e[] 来存边,e[u] 存储的是 \(u\) 的出边的信息(终点,边权等)

复杂度
  • 查询是否存在 \(u\)\(v\) 的边 \(O(d^+(u))\)
  • 遍历结点 \(u\) 的所有出边 \(O(d^+(u))\)
  • 遍历全图 \(O(n+m)\)
  • 空间复杂度 \(O(m)\)
优点与缺点
  • 适用于稀疏图,空间复杂度小
  • 查询一条边是否存在时效率较低
代码
#include<bits/stdc++.h>
using namespace std;

const int MAX_N = 5000 + 5;
struct node{
    int v, w;
};
vector<node> e[MAX_N];
int n, m;

void add(int u, int v, int w)
{
    node a;
    a.v = v;
    a.w = w;
    e[u].push_back(a);
}

int main()
{
    cin >> n >> m;
    for(int i = 1; i <= m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w);
    }
    return 0;
}

链式前向星

原理

本质上是用链表(数组)实现的邻接表

复杂度

同邻接表

优点与缺点
  • 有邻接表的优点,且效率较高
  • 查询一条边时效率较低
代码
#include<bits/stdc++.h>
using namespace std;

const int MAX_N = 5000 + 5;
struct node{
    int u, v, w;
    int next;
}e[MAX_N];
int n, m;
int cnt;
int head[MAX_N];

void init()
{
    cnt = 0;
    memset(head, -1, sizeof(head));
}

void add(int u, int v, int w)
{
    e[cnt].u = u;
    e[cnt].v = v;
    e[cnt].w = w;
    e[cnt].next = head[u];
    head[u] = cnt++;
}

int main()
{
    cin >> n >> m;
    init();
    for(int i = 1; i <= m; i++){
        int u, v, w;
        cin >> u >> v >> w;
        add(u, v, w);
    }
    return 0;
}

对结点 \(u\) 的出边遍历

for(int i = head[u]; i != -1; i = e[i].next) {
    ......
}
posted @ 2021-12-26 20:29  f(k(t))  阅读(31)  评论(0编辑  收藏  举报