第七十七课 最小生成树(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 }

结果如下:

小结:

原文地址:https://www.cnblogs.com/wanmeishenghuo/p/9734223.html