美文网首页
数据结构与算法基础九:图的存储结构

数据结构与算法基础九:图的存储结构

作者: Trigger_o | 来源:发表于2021-06-16 18:17 被阅读0次

    图的存储结构比线性表和树就要复杂多了,图的顶点没有顺序的概念,任何一个顶点都可以是起始,下面四张图其实是同一个图形结构.


    其实是同一个图

    真是的场景下会有复杂的多的情况出现,顺序存储完全无法实现,即使是多重链表,由于顶点的度可能差别很大,就得设置很多个指针域,效率很低.

    一:邻接矩阵

    先用一个一位数组来存储顶点数据,然后用一个二维数组来存储连通关系,二维数组在这里就是一个矩阵.
    图G(V,{E})有n个顶点,一个二维数组arc(nxn),如果v1v2有边,即v1v2 ∈ E,则arc[1][1] = 1,否则为0.


    数组arc

    1.无向图
    看一个示例,下图左是一个图,右边是数据的数组和边的数组;
    对角线在图的概念中是无意义,设置为0,
    例如第二行,提现了v1和v0,v2,v3的连通关系,也能得到v1的度是2;
    能看的v1和v3不连通,那么因为是无向图,同样的v3和v1也不连通,因此无向图的矩阵是对称的.对称矩阵的Aij = Aji.
    想知道vi的度和邻接点,遍历第i行就可以了.

    矩阵

    2.有向图
    有向图无非就是不对称了,存在弧的是1,不存在是0.

    有向图的矩阵

    对于网的情况,也就是带权的有向图,矩阵需要修改,因为权可能为0,可能是负数,因此我们可以根据具体情况设置,比如swift中设置一个Float的.infinity,这里用∞表示.



    网的矩阵

    二:邻接表

    通过邻接矩阵,我们可以发现,对于稀疏图,也就是边很少顶点很多的图,矩阵有点太浪费了.
    在树的存储结构中,有一种孩子表示法,这里也可以使用,于是就有了一种数组和链表结合(或者两个链表)的存储方法,叫做邻接表.
    首先用一个数组存储顶点,每个元素分为数据域和指针域,指针域连接一个单链表,可以叫做边表,对于下面的无向图,
    v0连通三个节点,因此v0的边表有三个节点.边表的节点也分为数据域和指针域,数据域存储顶点的下标,指针指向下个节点.
    对于这个结构,想知道某个顶点的度,和那些顶点连通就很容易找到.


    邻接表

    对于有向图,可以选择以弧尾来存储边表,也可以用弧头来存储边表,叫做逆邻接表.


    邻接表和逆邻接表

    对于带权的网图,在边表增加一个权的数据域即可,这样就可以描述边的权值.


    网的邻接表

    三:十字链表

    对于有向图,邻接表只体现了出度,逆邻接表只体现了入度,而十字链表就是把邻接表和逆邻接表结合起来.
    首先定义顶点的结构:data是数据,firstin是一条进入的弧,firstout是一条出去的弧.
    然后将顶点存储在一个数组A中


    顶点的结构

    然后定义弧:tailvex是这条弧的终点,也就是弧头,存的是数组A中顶点的下标,headvex是这条弧的起点,也就是弧尾,存的也是数组A中顶点的下标;
    headlink是指针,指向另一条终点相同的弧,同样的taillink也是指针,指向起点相同的另一条弧.
    需要注意这里有先后顺序,不会互相指来指去.


    弧的结构

    下面这张图是十字链表的结构.这张图看起来复杂,其实从它的定义这个角度来看就清晰了,十字链表是把邻接表和逆邻接表结合起来,而下面这图的实线就是邻接表,虚线就是逆邻接表.


    十字链表

    四:邻接多重表

    前面说到无向图的邻接表,它是针对顶点的,对于边其实是重复定义的,如果要删除某一条边,需要删除两个链表里的两个节点.
    比如下面这图要删除v0v2这条边,需要把打勾的节点删掉.


    删除边

    现在仿照十字链表的方式来改造一下;
    首先顶点的结构分为数据域和指针域,然后存储在数组中;
    然后边表节点结构为两个数据域ivex和jvex,存储的是一条边的两个顶点,还有指针ilink指向另一个有顶点ivex的边,指针jlink指向另一个含有顶点jvex的边.


    边表节点结构

    对于下面的这个无向图,一共四个顶点,五条边,首先把顶点和边都创建出来:


    先创建顶点和边

    现在顶点和边已经有了,再来连线,,虽然无向图不存在方向,但是再连线的时候考虑方向可以实现单循环,这样连线全都是唯一的,既不会漏,也不会存在重复.
    首先以四个顶点为起点,先连接4条边,也就是①到④;
    然后找边01的ilink,它应该是以0为终点的,那么只有一个就是02,也就是⑤,而01的jlink,应该指向是以1终点的,发现没有,于是是空;
    接着边12的ilink是以1位终点的,则是01,也就是⑦,jlink是以2位终点的,则是02,也就是⑨;


    连线

    五:边集数组

    对于非常关注边的情况下,边集数组可以很好的发挥作用;由两个数组组成,一个存储顶点,另一个存储起点和终点,当然还可以再加上权,访问信息等等.


    边集数组

    对于边集数组,之后在图的应用中还会提到.


    边集数组

    相关文章

      网友评论

          本文标题:数据结构与算法基础九:图的存储结构

          本文链接:https://www.haomeiwen.com/subject/ksfpeltx.html