第七十七课 最小生成树(Kruskal)
Posted wanmeishenghuo
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了第七十七课 最小生成树(Kruskal)相关的知识,希望对你有一定的参考价值。
添加kruskal算法:
1 #ifndef GRAPH_H 2 #define GRAPH_H 3 4 #include "Object.h" 5 #include "SharedPointer.h" 6 #include "Array.h" 7 #include "DynamicArray.h" 8 #include "LinkQueue.h" 9 #include "LinkStack.h" 10 #include "Sort.h" 11 12 namespace DTLib 13 { 14 15 template < typename E > 16 struct Edge : public Object 17 { 18 int b; 19 int e; 20 E data; 21 22 Edge(int i=-1, int j=-1) 23 { 24 b = i; 25 e = j; 26 } 27 28 Edge(int i, int j, const E& value) 29 { 30 b = i; 31 e = j; 32 data = value; 33 } 34 35 bool operator == (const Edge<E>& obj) 36 { 37 return (b == obj.b) && (e == obj.e); //在这里不关注权值大小 38 } 39 40 bool operator != (const Edge<E>& obj) 41 { 42 return !(*this == obj); 43 } 44 45 bool operator < (const Edge<E>& obj) 46 { 47 return (data < obj.data); 48 } 49 50 bool operator > (const Edge<E>& obj) 51 { 52 return (data > obj.data); 53 } 54 }; 55 56 template < typename V, typename E > 57 class Graph : public Object 58 { 59 protected: 60 template < typename T > 61 DynamicArray<T>* toArray(LinkQueue<T>& queue) 62 { 63 DynamicArray<T>* ret = new DynamicArray<T>(queue.length()); 64 65 if( ret != NULL ) 66 { 67 for(int i=0; i<ret->length(); i++, queue.remove()) 68 { 69 ret->set(i, queue.front()); 70 } 71 } 72 else 73 { 74 THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret object..."); 75 } 76 77 return ret; 78 } 79 80 SharedPointer< Array<Edge<E> > > getUndirectedEdges() 81 { 82 DynamicArray<Edge<E>>* ret = NULL; 83 84 if( asUndirected() ) 85 { 86 LinkQueue<Edge<E>> queue; 87 88 for(int i=0; i<vCount(); i++) 89 { 90 for(int j=i; j<vCount(); j++) 91 { 92 if( isAdjacent(i, j) ) 93 { 94 queue.add(Edge<E>(i, j, getEdge(i, j))); 95 } 96 } 97 } 98 99 ret = toArray(queue); 100 } 101 else 102 { 103 THROW_EXCEPTION(InvalidOperationException, "This function is for undirected graph only..."); 104 } 105 106 return ret; 107 } 108 109 int find(Array<int>& p, int v) 110 { 111 while( p[v] != -1) 112 { 113 v = p[v]; 114 } 115 116 return v; 117 } 118 public: 119 virtual V getVertex(int i) = 0; 120 virtual bool getVertex(int i, V& value) = 0; 121 virtual bool setVertex(int i, const V& value) = 0; 122 virtual SharedPointer< Array<int> > getAdjacent(int i) = 0; 123 virtual bool isAdjacent(int i, int j) = 0; 124 virtual E getEdge(int i, int j) = 0; 125 virtual bool getEdge(int i, int j, E& value) = 0; 126 virtual bool setEdge(int i, int j, const E& value) = 0; 127 virtual bool removeEdge(int i, int j) = 0; 128 virtual int vCount() = 0; 129 virtual int eCount() = 0; 130 virtual int OD(int i) = 0; 131 virtual int ID(int i) = 0; 132 133 virtual int TD(int i) 134 { 135 return ID(i) + OD(i); 136 } 137 138 bool asUndirected() 139 { 140 bool ret = true; 141 142 for(int i=0; i<vCount(); i++) 143 { 144 for(int j=0; j<vCount(); j++) 145 { 146 if( isAdjacent(i, j) ) 147 { 148 ret = ret && isAdjacent(j, i) && (getEdge(i, j) == getEdge(j, i)); 149 } 150 } 151 } 152 153 return ret; 154 } 155 156 SharedPointer< Array< Edge<E > > > prim(const E& LIMIT, const bool MINIUM = true) //参数为理论上的最大权值 157 { 158 LinkQueue< Edge<E> > ret; 159 160 if( asUndirected() ) 161 { 162 DynamicArray<int> adjVex(vCount()); 163 DynamicArray<bool> mark(vCount()); 164 DynamicArray<E> cost(vCount()); 165 SharedPointer< Array<int> > aj = NULL; 166 bool end = false; 167 int v = 0; 168 169 for(int i=0; i<vCount(); i++) 170 { 171 adjVex[i] = -1; 172 mark[i] = false; 173 cost[i] = LIMIT; 174 } 175 176 mark[v] = true; 177 178 aj = getAdjacent(v); 179 180 for(int j=0; j<aj->length(); j++) 181 { 182 cost[(*aj)[j]] = getEdge(v, (*aj)[j]); 183 adjVex[(*aj)[j]] = v; 184 } 185 186 for(int i=0; (i<vCount()) && !end; i++) 187 { 188 E m = LIMIT; 189 int k = -1; 190 191 for(int j=0; j<vCount(); j++) 192 { 193 if( !mark[j] && (MINIUM ? (cost[j] < m) : (cost[j] > m))) 194 { 195 m = cost[j]; 196 k = j; 197 } 198 } 199 200 end = (k == -1); 201 202 if( !end ) 203 { 204 ret.add(Edge<E>(adjVex[k], k, getEdge(adjVex[k], k))); 205 206 mark[k] = true; 207 208 aj = getAdjacent(k); 209 210 for(int j=0; j<aj->length(); j++) 211 { 212 if( !mark[(*aj)[j]] && (MINIUM ? (getEdge(k, (*aj)[j]) < cost[(*aj)[j]]) : (getEdge(k, (*aj)[j]) > cost[(*aj)[j]])) ) 213 { 214 cost[(*aj)[j]] = getEdge(k, (*aj)[j]); 215 adjVex[(*aj)[j]] = k; 216 } 217 } 218 } 219 } 220 } 221 else 222 { 223 THROW_EXCEPTION(InvalidOperationException, "Prim operator is for undirected graph only..."); 224 } 225 226 if( ret.length() != (vCount() - 1) ) 227 { 228 THROW_EXCEPTION(InvalidOperationException, "No enough edge for prim operation..."); 229 } 230 231 return toArray(ret); 232 } 233 234 SharedPointer< Array<Edge<E> > > kruskal(const bool MINMUM = true) 235 { 236 LinkQueue< Edge<E> > ret; 237 238 SharedPointer< Array< Edge<E> > > edges = getUndirectedEdges(); 239 240 DynamicArray<int> p(vCount()); //前驱标记数组 241 242 for(int i=0; i<p.length(); i++) 243 { 244 p[i] = -1; 245 } 246 247 Sort::Shell(*edges, MINMUM); 248 249 for(int i=0; (i<edges->length()) && (ret.length() < (vCount() - 1)); i++) 250 { 251 int b = find(p, (*edges)[i].b); 252 int e = find(p, (*edges)[i].e); 253 254 if( b != e ) 255 { 256 p[e] = b; 257 258 ret.add((*edges)[i]); 259 } 260 } 261 262 if( ret.length() != (vCount() - 1) ) 263 { 264 THROW_EXCEPTION(InvalidOperationException, "No enough edges for Kruskal operation..."); 265 } 266 267 return toArray(ret); 268 } 269 270 SharedPointer< Array<int> > BFS(int i) 271 { 272 DynamicArray<int>* ret = NULL; 273 274 if( (0 <= i) && (i < vCount()) ) 275 { 276 LinkQueue<int> q; 277 LinkQueue<int> r; 278 DynamicArray<bool> visited(vCount()); 279 280 for(int i=0; i<visited.length(); i++) 281 { 282 visited[i] = false; 283 } 284 285 q.add(i); 286 287 while( q.length() > 0 ) 288 { 289 int v = q.front(); 290 291 q.remove(); 292 293 if( !visited[v] ) 294 { 295 SharedPointer< Array<int> > aj = getAdjacent(v); 296 297 for(int j=0; j<aj->length(); j++) 298 { 299 q.add((*aj)[j]); 300 } 301 302 r.add(v); 303 304 visited[v] = true; 305 } 306 } 307 308 ret = toArray(r); 309 } 310 else 311 { 312 THROW_EXCEPTION(InvalidParameterException, "Index i is invalid..."); 313 } 314 315 return ret; 316 } 317 318 SharedPointer< Array<int> > DFS(int i) 319 { 320 DynamicArray<int>* ret = NULL; 321 322 if( (0 <= i) && (i < vCount()) ) 323 { 324 LinkStack<int> s; 325 LinkQueue<int> r; 326 DynamicArray<bool> visited(vCount()); 327 328 for(int j=0; j<visited.length(); j++) 329 { 330 visited[j] = false; 331 } 332 333 s.push(i); 334 335 while( s.size() > 0 ) 336 { 337 int v = s.top(); 338 339 s.pop(); 340 341 if( !visited[v] ) 342 { 343 SharedPointer< Array<int> > aj = getAdjacent(v); 344 345 for(int j=aj->length() - 1; j>=0; j--) 346 { 347 s.push((*aj)[j]); 348 } 349 350 r.add(v); 351 352 visited[v] = true; 353 } 354 } 355 356 ret = toArray(r); 357 } 358 else 359 { 360 THROW_EXCEPTION(InvalidParameterException, "Index i is invalid..."); 361 } 362 363 return ret; 364 } 365 366 }; 367 368 } 369 370 #endif // GRAPH_H
测试程序如下:
1 #include <iostream> 2 #include "MatrixGraph.h" 3 #include "ListGraph.h" 4 5 using namespace std; 6 using namespace DTLib; 7 8 template< typename V, typename E > 9 Graph<V, E>& GraphEasy() 10 { 11 static MatrixGraph<4, V, E> g; 12 13 g.setEdge(0, 1, 1); 14 g.setEdge(1, 0, 1); 15 16 g.setEdge(0, 2, 3); 17 g.setEdge(2, 0, 3); 18 19 g.setEdge(1, 2, 1); 20 g.setEdge(2, 1, 1); 21 22 g.setEdge(1, 3, 4); 23 g.setEdge(3, 1, 4); 24 25 g.setEdge(2, 3, 1); 26 g.setEdge(3, 2, 1); 27 28 return g; 29 } 30 31 template< typename V, typename E > 32 Graph<V, E>& GraphComplex() 33 { 34 static ListGraph<V, E> g(9); 35 36 g.setEdge(0, 1, 10); 37 g.setEdge(1, 0, 10); 38 39 g.setEdge(0, 5, 11); 40 g.setEdge(5, 0, 11); 41 42 g.setEdge(1, 2, 18); 43 g.setEdge(2, 1, 18); 44 45 g.setEdge(1, 8, 12); 46 g.setEdge(8, 1, 12); 47 48 g.setEdge(1, 6, 16); 49 g.setEdge(6, 1, 16); 50 51 g.setEdge(2, 3, 22); 52 g.setEdge(3, 2, 22); 53 54 g.setEdge(2, 8, 8); 55 g.setEdge(8, 2, 8); 56 57 g.setEdge(3, 8, 21); 58 g.setEdge(8, 3, 21); 59 60 g.setEdge(3, 6, 24); 61 g.setEdge(6, 3, 24); 62 63 g.setEdge(3, 7, 16); 64 g.setEdge(7, 3, 16); 65 66 g.setEdge(3, 4, 20); 67 g.setEdge(4, 3, 20); 68 69 g.setEdge(4, 5, 26); 70 g.setEdge(5, 4, 26); 71 72 g.setEdge(4, 7, 7); 73 g.setEdge(7, 4, 7); 74 75 g.setEdge(5, 6, 17); 76 g.setEdge(6, 5, 17); 77 78 g.setEdge(6, 7, 19); 79 g.setEdge(7, 6, 19); 80 81 return g; 82 } 83 84 int main() 85 { 86 Graph<int, int>& g = GraphComplex<int, int>(); 87 88 SharedPointer< Array< Edge<int> > > sa = g.kruskal(); 89 90 int w = 0; 91 92 for(int i=0; i<sa->length(); i++) 93 { 94 w += (*sa)[i].data; 95 cout << (*sa)[i].b << " " << (*sa)[i].e << " " << (*sa)[i].data << endl; 96 } 97 98 cout << "Weight: " << w << endl; 99 100 return 0; 101 }
结果如下:
小结:
以上是关于第七十七课 最小生成树(Kruskal)的主要内容,如果未能解决你的问题,请参考以下文章
最小生成树matlab代码Kruskal算法,用于二维网络生成