• 图论基础——建图 笔记与思路整理


    今天上课的时候Zimo_Lee说他把如何建图给忘了……在嘲笑他的同时写一篇随笔,也整理一下自己的思路。

    先贴一张VisuAlgo(真香)上的图:

    这是一张有向有权图,讲解就围绕这个开始。如果是无向图,就每次建边时建一条反向边即可。


    一、邻接矩阵

    原理很简单,如果graph[i][j]存在数据x,则代表有一条边从i指向j,权为x。代码应该也不用多解释:

    graph[100][100];
    void add_edge(int from, int to, int value){
        graph[from][to] = value;
    }

    邻接矩阵很好理解,代码很简单,而且在有时遍历会很方便。缺点也很明显,当图比较稀疏的时候需要很多不必要的空间,会造成很大的空间浪费。

    二、邻接表

    同一个点发出的边存在一个数组里。相对来说会比邻接矩阵省空间,也可以很方便地遍历同一个点发出的所有边。

    由于动态数组需要,我习惯使用vector存储每个结点。

    graph[i][cnt] = (j, x)表示第i个点发出的第cnt条边指向j,权为x。代码:

    struct edge{
        int to, val;
    };
    vector<edge> graph[100];
    void add_edge(int from, int to, int value){
        graph[from].push_back((edge){to, value});
    }

    三、邻接链表

    整个表中的每一个元素代表一条边,边的起始、结束与权值均存储在这个元素中(一般用结构体)。经过优化后的邻接链表用一个first[]数组存储每个点中的第一条边,结构体中增加一项next存储同一起始结点的下一条边。这样,想要遍历所有从n号结点起始的边,只要使用

    for(int i=first[n]; i; i=graph[i].next)  

    即可,时间上与邻接表基本一致。

    在代码实现上,优化只需要每次建边时把之前的first[from]设置为当前边的next,first[from]改为当前边的序号。代码:

    struct edge{
        int to, val, next;
    };
    edge graph[10000];
    int first[100], edge_cnt = 0;
    void add_edge(int from, int to, int value){
        graph[++edge_cnt] = (edge){to, value, first[from]};
        first[from] = edge_cnt;
    }

    这三种是c++建图的最常用方式,要根据实际情况具体分析选择合适的存储结构。并不是越复杂的结构就越好用

  • 相关阅读:
    lnmp yum源的安装自己总结。
    bootstrap 表单validator与ajax验证!!!!
    laravel5.4 安装
    学习进度条
    作业8:单元测试练习(个人练习)
    作业7: 用户体验设计案例分析
    学生成绩录入系统设计与实现(1)
    作业5:需求分析
    结对项目—— 词频统计
    结对项目—— 词频统计
  • 原文地址:https://www.cnblogs.com/miserweyte/p/11469438.html
Copyright © 2020-2023  润新知