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