最近看了很多介绍图算法的文章,发现网上可以搜到的资料比较少,所以打算在这写一个介绍图算法的系列文章,一方面是帮助自己整理,另一方面也给大家分享下这方面的知识。
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
时间: 2024-11-08 19:48:50