igraph/networkx学习笔记之一 —— 数据结构

      首先,基本上所有的graph library都有其局限性,不同的数据结构有优点的同时必然有缺点,图算法对数据结构的依赖性构成另一个原因。所以如果是想用一个工具包解决所有的问题显然是一种奢望,很多时候甚至必须要从头写自己的代码。但是阅读igraph和networkx这样成型了的函数库对熟悉算法和相关语言的技巧是很有用的。

 

      igraph(http://igraph.sourceforge.net/)是在处理复杂网络问题中用的比较多的C语言函数库,不过它也提供了R,python的接口。

 

      networkx(http://networkx.lanl.gov/)是用基于python的dictionary的一个复杂网络库。众所周知的是,python语言在对程序效率要求不是很苛刻的时候是构建程序的最佳选择一(对python不熟悉的图论研究者可以看看我在人人上的一篇日志(http://blog.renren.com/blog/bp/QmicNX45As),而用python语言写成的networkx充分利用了python中的dictionary的特性,将python的动态性发挥到了极致,研究networkx源代码对于研究算法和做相关的实验是我们的不二选择。但是对于规模很大的问题,性能上的要求需要我们去使用诸如igraph,BGL(boost graph library,不过基本已经停止开发)之类用C/C++写成的库。

 

 

igraph中图的数据结构

      igraph中基本的graph structure采用的是EdgeList,所以在igraph中自然而然的允许multiedge的存在,当然它也提供了Adjancency list(对某些算法,大部分算法接受的参数是edgelist)。数据结构igraph_t定义如下:

typedef struct igraph_s { igraph_integer_t n; igraph_bool_t directed; igraph_vector_t from; igraph_vector_t to; igraph_vector_t oi; igraph_vector_t ii; igraph_vector_t os; igraph_vector_t is; void *attr; } igraph_t;

(注意igraph中顶点和边都是从0开始编号一直到总数减一)。其中n是图的顶点个数,directed标志是否是有向图。所有边的顶点存储在from和to两个向量(igraph_vector_t)中,oi[e]对应的是编号为e的边所对应的尾结点在from中的index,同样ii[e]对应于e的头节点在to中的index(也就是是说e 可以表示为 from[oi[e]] -> to[ii[e]])。所以from,to,oi,ii都是长度与边数相同的向量。os和is则和oi,ii相反,表示的是从顶点到边的映射,从顶点v出发的第一条边为 from[oi[os[v]]] -> to[ii[os[v]]],所以当os[v] == os[v + 1]时候就表示从该顶点没有出边。向量is同理。os,is都是长度为顶点数加一的向量。操作igraph_t的一些基本API如igraph_empty, igraph_adjacent等见于文档手册(btw,igraph的文档写的很全很好,有空应该研究一下它制作文档的技术)。

 

      因为采用的是edgelist的结构,所以增/减边(顶点)的操作在igraph中是相当耗费时间的。add和delete操作的时间复杂度基本上都是O(|V| + |E|)或者O(|V|)。(oops!)

 

      igraph实现了自己的一套数据结构诸如vector, heap,hashtable(一般的C程序库都是这么干的,C程序员总是重复制造轮子么。。。),因为C没有C++/JAVA中的泛型,一般都是采取void*指针或者宏的方式来实现泛型。igraph采用的是后者。大致看了一下,感觉收获还是很多的。igraph将类型无关的代码都抽象出来放在*pmt.h *pmt这样的文件模板里面。types.h和相关的C文件中则利用这些代码模板生成相应的声明和定义。一个典型的代码片段如下:

#define BASE_BOOL #include "igraph_pmt.h" #include "vector.pmt" #include "igraph_pmt_off.h" #undef BASE_BOOL


 

其中vector.pmt定义的是类型无关的代码,igraph_pmt_off.h则小心翼翼的将宏清除出去(再一次感慨C++有模板真是太好了。。。)。这种手法还是有借鉴意义的(比起void*我更喜欢这样)。

 

      另外还学到了#error可以用来检测编译期间的错误(又一次证明我对C的了解还是太少太少。。。汗)。

 

      igraph的基本数据结构就写这么多,感兴趣的研究者可以去看API文档和相应的源码。算法留待下回分解,igraph中最出彩的部分就是它实现了相当一部分较新的复杂网络算法(包括网络流、图同构、匹配算法以及社团结构等)。

 

Networkx的数据结构

      得益于python语言的简洁明快,所以看Networkx的源码基本上是一览无余,这应该就是Knuth所说的Literate Programming吧。Networkx中图的数据结构主要有Graph(简单无向图), DiGraph(简单有向图), MultiGraph(允许有重边的无向图)和MultiDiGraph(允许有重边的有向图)。他们的实现都扎根于Python字典类的强大(Oreilly出版的《代码之美》一书中称Python的Dictionary类为全能战士,此话一点不错!)。关于Networkx的数据结构我这里就不赘述了,Python代码最好的解释了它自己。(再次向大家推荐Python编程语言! -_- )。

 

 

你可能感兴趣的:(C/C++,Python,数据结构,python,vector,dictionary,算法,graph)