图算法系列-图的简单实现

最近看了很多介绍图算法的文章,发现网上可以搜到的资料比较少,所以打算在这写一个介绍图算法的系列文章,一方面是帮助自己整理,另一方面也给大家分享下这方面的知识。

1.1图的定义:
图(graph)由顶点(vertex)和边(edge)的集合组成,每一条边就是一个点对(v,w)。

图的种类:地图,电路图,调度图,事物,网络,程序结构

图的属性:有V个顶点的图最多有V*(V-1)/2条边

图算法系列-图的简单实现

图算法系列-图的简单实现图算法系列-图的简单实现
1.2图的ADT:

 1 struct Edge{

 2 int v,w;

 3 Edge(int a=-1,int b=-1):v(a),w(b){}

 4 };

 5 

 6 class Graph

 7 {

 8 private:

 9 //

10 public:

11 Graph(int,bool);

12 ~Graph();

13 int V() const;//顶点

14 int E() const;//

15 bool directed() const;//是否有方向

16 int insert(Edge);

17 int remove(Edge);

18 bool edge(int,int);

19 //迭代器

20 class adjIterator

21 {

22 public:

23 adjIterator(const Graph&,int);

24 int begin();

25 int next();

26 bool end();

27 };

28 };

 

图的构造函数将图中可能的最大顶点数作为一个参数。

1.3邻接矩阵:
邻接矩阵是一个元素为bool值的V*V矩阵,若图中存在一条连接顶点V和W的边,折矩阵adj[v][w]=1,否则为0。占用的空间为V*V,当图是稠密时,邻接矩阵是比较合适的表达方法。

图算法系列-图的简单实现

//graph ADT实现(邻接矩阵)

 1 class DenseGraph

 2 {

 3 public:

 4 DenseGraph(int v,bool digraph=false):adj(v),Vcnt(v),Ecnt(0),diGraph(digraph){

 5 for(int i=0;i<v;++i)

 6 adj[i].assign(v,false);//将邻接矩阵初始化为false

 7 }

 8 int V() const{

 9 return Vcnt;

10 }

11 int E() const{

12 return Ecnt;

13 }

14 bool directed() const{

15 return diGraph;

16 }

17 void insert(Edge e)

18 {

19 int v=e.v,w=e.w;

20 if(adj[v][w]==false) Ecnt++;

21 adj[v][w]=true;

22 if(!digraph) adj[w][v]=true;

23 }

24 void remove(Edge e)

25 {

26 

27 int v=e.v,w=e.w;

28 if(adj[v][w]==true) Ecnt--;

29 adj[v][w]=false;

30 if(!digraph) adj[w][v]=false;

31 }

32 bool edge(int v,int w) const

33 {

34 return adj[v][w];

35 }

36 class adjIterator;

37 friend class adjIterator;

38 

39 private:

40 int Vcnt;//顶点数

41 int Ecnt;//边数

42 bool diGraph;//是否有向图

43 vector< vector<bool> > adj;//邻接矩阵

44 };

45 

46 //邻接矩阵的迭代器,返回顶点vertex的下一个相邻的顶点

47 class DenseGraph::adjIterator

48 {

49 public:

50 adjIterator(const DenseGraph &g,int vertex):

51 G(g),v(vertex),i(-1){}

52 int begin()

53 {

54 i=-1;

55 return next();

56 }

57 int next()

58 {

59 for(i++;i<G.V();++i)

60 if(G.adj[v][i]==true) return i;

61 return -1;

62 }

63 bool end()

64 {

65 return i>=G.V();

66 }

67 private:

68 const DenseGraph &G;

69 int i,v;

70 };

 

1.4邻接表的表示
对于非稠密的图,使用邻接矩阵有点浪费存储空间,可以使用邻接表,我们维护一个链表向量,给定一个顶点时,可以立即访问其链表,占用的空间为O(V+E)。

图算法系列-图的简单实现

//程序:Graph的邻接表实现

 1 class SparseGraph()

 2 {

 3 public:

 4 SparseGraph(int v,bool digraph=false):

 5 Vcnt(v),Ecnt(0),diGraph(digraph){

 6 adj.assign(v,0);

 7 }

 8 SparseGraph(const SparseGraph& G);

 9 ~SparseGraph();

10 int V() const{

11 return Vcnt;

12 }

13 int E() const{

14 return Ecnt;

15 }

16 bool directed(){

17 return digraph;

18 }

19 //往图中插入一条边

20 void insert(Edge e){

21 int v=e.v,w=e.w;

22 adj[v]=new node(w,adj[v]);

23 if(!diGraph) adj[w]=new node(v,adj[w]);

24 Ecnt++;

25 }

26 void remove(Edge e);

27 bool Edge(int v,int w) const;

28 class adjIterator;//邻接表的迭代器

29 friend class adjIterator;//把迭代器类设置为友元类

30 private:

31 int Vcnt,Ecnt;

32 bool diGraph;

33 struct node

34 {

35 int v;

36 node* next;

37 node(int x,node* t):v(x),next(t){}

38 };

39 typedef node* link;

40 vector<link> adj;//邻接表

41 };

42 

43 //邻接表迭代器的实现

44 class SparseGraph::adjIterator

45 {

46 public:

47 adjIterator(const SparseGraph& g,int v):

48 G(g),v(v),curLink(0){}

49 adjIterator(const adjIterator&);

50 ~adjIterator();

51 int begin(){

52 curLink=adj[v];

53 return curLink?curLink-v:-1;

54 

55 }

56 int next(){

57 if(curLink) curLink=curLink->next;

58 return curLink?curLink->v:-1;

59 }

60 bool end(){

61 return curLink==0;

62 }

63 private:

64 const SparseGraph& G;

65 int v;//顶点编号

66 link curLink;

67 };

 

1.5简单路径搜索
给定两个顶点,图中是否存在一条连接起来的简单路径呢?
比如给定顶点V和W,对于和V相邻的每个顶点t,是否存在从t到W的简单路径,然后递归调用,我们使用一个顶点访问向量visited来对顶点标记防止重复访问。

//程序:简单路径搜索

 1 template <class Graph> class SearchPath

 2 {

 3 

 4 public:

 5 SearchPath(const Graph& g,int v,int w):

 6 G(g),visited(g.V(),false){

 7 found=search(v,w);

 8 }

 9 bool existed() const

10 {

11 return found;

12 }

13 private:

14 const Graph& G;

15 vector<bool> visited;

16 bool found;

17 bool search(int v,int w)

18 {

19 if(v=w) return true;

20 visited[v]=true;
21 typename Graph::adjIterator ite(G,v); 22 for(int t=ite.begin();!ite.end();t=ite.next()) 23 if(!visited[t]) 24 if(search(t,w)) return true; 25 return false; 26 } 27 };

 

 参考资料:维基百科http://en.wikipedia.org/wiki/Category:Graph_algorithms

      Graph algorithm:http://www-users.cs.umn.edu/~karypis/parbook/Lectures/AG/chap10_slides.pdf

      原文地址:http://lippiouyangonline.info/algorithm/2013/12/29/graph.html

你可能感兴趣的:(算法)