图基本算法之图的存储

来源:互联网 发布:ppt软件下载官方 编辑:程序博客网 时间:2024/06/07 06:45

图是一种很常用的数据结构,其算法的难度相比其他数据结构,难度更大一些,本编文章,将对图的一些基本概念和存储做一些讲解。

图是由顶点集(V)和边集(E)组成,记为 G = (V,E) ; 其中,顶点集不能为空,边集可以为空。图分为以下两种:

1. 有向图

若 E 是有向边(弧)的有限集合时,则图 G  为有向图。其中,弧是顶点的有序对。

2. 无向图

若 E 是无向边(边)的有限集合时,则图 G 为无向图。其中,边是顶点的无序对。

通过以上,明确了图的基本定义,下面讨论图中一些重要的概念:

1.图中顶点的度,入度和出度

顶点的度的定义:以该定点为一个端点的边的数目

对于无向图,定点 V 的度是指依附于该定点的边的条数,记为 TD(V)。在具有 n 个定点 e 条边的无向图中,有 ∑TD(v) = 2e, 即无向图的全部定点的度之和等于边数的两倍。

对于有向图,定点 v 的度分为入度和出度。其中,有向图的全部定点的入度之和与出度之和相等,且等于边数。

其他一些概念在此不做详述。以下主要就图的存储方式给以说明:

图的存储必须要完整,准确的反应顶点集和边集的信息,根据不同图的结构和算法,可以采用不同的存储方式,而且不同的存储方式将对算法的效率产生相当大的影响。无论是有向图还是无向图,主要的存储方式有两种:邻接矩阵(顺序存储)和邻接表(链接存储)。

1. 邻接矩阵

所谓的邻接矩阵,就是用一个一维数组存储图中定点的信息,用一个二维数组存储图中边的信息(各定点的邻接关系),存储定点之间邻接关系的二维数组称为邻接矩阵。邻接矩阵式一个 n*n 的方阵(n 表示点的数目)。

对于无权图而言,其二维数组中的定义为:

  • A[i][j] =  1      若 ( v[i], v[j] )是 E (G) 中的边
  • A[i][j] =  0      若 ( v[i], v[j] )不是E(G) 中的边

注意,其对于无向图而言,是一个对称的矩阵。

用邻接矩阵存储时,很容易获得任意两个顶点时间是否右边相连接,但是,要确定图中有多少边,需按行,列对每个元素进行遍历,花费代价较大。


2. 临接表法

当一个图是稀疏图时,使用邻接矩阵会浪费较大的空间,而临界表结合了顺序存储和链式存储,大大减少了不必要的空间浪费。

邻接表就是对图的每个顶点建立一个单链表,第 i 个单链表中的节点表示依附于顶点 V(i) 的边,每个元素都是由顶点域和指针构成,下面给出其定义:

struct node{    node():next(nullptr){}    int val;    struct node *next;};


下面给出由邻接矩阵向邻接表转换的代码片段:

void buildLink(const int (*v)[5], node link[]){    for( int i = 0; i < sz; ++i )    {        link[i].val = i;    }    for( int i = 0; i < sz; ++i )    {        node *t = &link[i];        for( int j = 0; j < sz; ++j )        {            if( v[i][j] != 0 )            {                node *s = new node();                s->val = j;                t->next = s;                t = s;            }        }    }}

通过以上代码可以完成对邻接矩阵存储的图到邻接表存储的转换。


对图的存储还有:十字链表以及邻接多重表的方法,这两个存储方式使用较少,在这里不做描述。


0 0
原创粉丝点击