• 图论-图的存储方式


    图的存储方式:

    1,数组表示法:

    用两个数组来存储图的信息

    • 顶点表:记录各个顶点信息的
    • 邻接矩阵:表示各个顶点之间的关系(有关为1,无关为0)

    注:无向图的邻接矩阵是对称的,有向图的邻接矩阵可能是不对称的。

    无向图的邻接矩阵

    结点i的度=邻接矩阵中第i行或第i列之和

    存储压缩:上三角矩阵或下三角矩阵(不含对角线)

    有向图的邻接矩阵

    结点i的出度=邻接矩阵中第i行之和

    结点i的入度=邻接矩阵中第i列之和

    A.edge[i][j]= 如果两点直接存在边且有权值,就记为权值,自环或者无边就记为∞

    优点:容易实现图的各种基本操作

    {

    查找顶点,

    判断顶点之间是否有边,仅仅耗费O(1)时间

    找顶点的邻接点

    }

    缺点:稀疏图,即使边数<<n^2,也需要占用O(n^2)的存储单元,读入数据需要耗费O(n^2)时间

    邻接矩阵表示方法,code:

     1 #include <iostream>
     2 #include <vector>
     3 
     4 using namespace std;
     5 
     6 int n, m;
     7 vector<bool> vis;
     8 vector<vector<bool> > adj;
     9 
    10 bool find_edge(int u, int v) { return adj[u][v]; }
    11 
    12 void dfs(int u) {
    13   if (vis[u]) return;
    14   vis[u] = true;
    15   for (int v = 1; v <= n; ++v) {
    16     if (adj[u][v]) {
    17       dfs(v);
    18     }
    19   }
    20 }
    21 
    22 int main() {
    23   cin >> n >> m;
    24 
    25   vis.resize(n + 1, false);
    26   adj.resize(n + 1, vector<bool>(n + 1, false));
    27 
    28   for (int i = 1; i <= m; ++i) {
    29     int u, v;
    30     cin >> u >> v;
    31     adj[u][v] = true;
    32   }
    33 
    34   return 0;
    35 }

    2,邻接表表示法

    图的一种链式存储结构

    顶点表:记录各个顶点的信息,通常以顺序结构存储,也可以链式存储(vector存储)

    邻接链表:为每个顶点建立一个单链表,表示依附于改顶点的所有边(对有向图是以该节点为尾的所有弧)

    无向图的邻接表

    优点:n个顶点,e条边的无向图,只需要n个头结点和2e个表节点。对稀疏图而言,比数组表示法节省存储空间。

    缺点:每条边需要对应两个表结点

    有向图的邻接表

    缺点

    {

    查找进入某个结点的弧不易

    求某个顶点的入度需要遍历整个邻接表

    }

    改进:建立逆邻接表

    邻接表表示法code:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int n, m;
    vector<bool> vis;
    vector<int> adj[n+1];
    
    bool find_edge(int u, int v) {
      for (int i = 0; i < adj[u].size(); ++i) {
        if (adj[u][i] == v) {
          return true;
        }
      }
      return false;
    }
    
    void dfs(int u) {
      if (vis[u]) return;
      vis[u] = true;
      for (int i = 0; i < adj[u].size(); ++i) dfs(adj[u][i]);
    }
    
    int main() {
      cin >> n >> m;
    
      vis.resize(n + 1, false);
      adj.resize(n + 1);
    
      for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        adj[u].push_back(v);
      }
    
      return 0;
    }

    3,链式前向星:

    本质上是用链表实现的邻接表,核心代码如下:

    // head[u] 和 cnt 的初始值都为 -1
    void add(int u, int v) {
      next[++cnt] = head[u];  // 当前边的后继
      head[u] = cnt;         // 起点 u 的第一条边
      to[cnt] = v;           // 当前边的终点
    }
    
    // 遍历 u 的出边
    for (int i = head[u]; ~i; i = next[i]) {  // ~i 表示 i != -1
      int v = to[i];
    }

    代码:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    int n, m;
    vector<bool> vis;
    vector<int> head, next, to;
    
    void add(int u, int v) {
      next.push_back(head[u]);
      head[u] = to.size();
      to.push_back(v);
    }
    
    bool find_edge(int u, int v) {
      for (int i = head[u]; ~i; i = nxt[i]) {  // ~i 表示 i != -1
        if (to[i] == v) {
          return true;
        }
      }
      return false;
    }
    
    void dfs(int u) {
      if (vis[u]) return;
      vis[u] = true;
      for (int i = head[u]; ~i; i = next[i]) dfs(to[i]);
    }
    
    int main() {
      cin >> n >> m;
    
      vis.resize(n + 1, false);
      head.resize(n + 1, -1);
    
      for (int i = 1; i <= m; ++i) {
        int u, v;
        cin >> u >> v;
        add(u, v);
      }
    
      return 0;
    }

    4,十字链表

    5,邻接多重表表示

    6,直接存边:

    #include <iostream>
    #include <vector>
    
    using namespace std;
    
    struct Edge {
      int u, v;
    };
    
    int n, m;
    vector<Edge> e;
    vector<bool> vis;
    
    bool find_edge(int u, int v) {
      for (int i = 1; i <= m; ++i) {
        if (e[i].u == u && e[i].v == v) {
          return true;
        }
      }
      return false;
    }
    
    void dfs(int u) {
      if (vis[u]) return;
      vis[u] = true;
      for (int i = 1; i <= m; ++i) {
        if (e[i].u == u) {
          dfs(e[i].v);
        }
      }
    }
    
    int main() {
      cin >> n >> m;
    
      vis.resize(n + 1, false);
      e.resize(m + 1);
    
      for (int i = 1; i <= m; ++i) cin >> e[i].u >> e[i].v;
    
      return 0;
    }
  • 相关阅读:
    javascript 模板系统 ejs v2
    三国观后感
    《非诚勿扰》乐嘉老师送给男生女生的话:
    正则学习笔记6
    硬链接和符号链接
    javascript 模板系统 ejs v1
    javascript模板系统 ejs v3
    程序员编程艺术:第八章、从头至尾漫谈虚函数
    程序员编程艺术第十一章:最长公共子序列(LCS)问题
    编程艺术第二十三~四章&十一续:杨氏矩阵查找,倒排索引关键词Hash编码
  • 原文地址:https://www.cnblogs.com/sweetlittlebaby/p/12813326.html
Copyright © 2020-2023  润新知