圖算法系列-圖的簡單實現

最近看了不少介紹圖算法的文章,發現網上能夠搜到的資料比較少,因此打算在這寫一個介紹圖算法的系列文章,一方面是幫助本身整理,另外一方面也給你們分享下這方面的知識。html

1.1圖的定義:
圖(graph)由頂點(vertex)和邊(edge)的集合組成,每一條邊就是一個點對(v,w)。node

圖的種類:地圖,電路圖,調度圖,事物,網絡,程序結構算法

圖的屬性:有V個頂點的圖最多有V*(V-1)/2條邊網絡


1.2圖的ADT:ide

 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,當圖是稠密時,鄰接矩陣是比較合適的表達方法。spa

//graph ADT實現(鄰接矩陣)code

 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)。htm

//程序:Graph的鄰接表實現blog

 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

相關文章
相關標籤/搜索