Grafalgo
Library of useful data structures and algorithms
/Users/jst/src/grafalgo/cpp/graphAlgorithms/mst/xtras/fastKruskal.cpp
00001 #include "stdinc.h"
00002 #include "Partition.h"
00003 #include "Wgraph.h"
00004 #include "List.h"
00005 
00006 using namespace grafalgo;
00007 
00008 // Sort edges according to weight, using heap-sort.
00009 void sortEdges(edge *elist, const Wgraph& wg) {
00010         int i, p, c; edge e; weight w;
00011 
00012         for (i = wg.m()/2; i >= 1; i--) {
00013                 // do pushdown starting at i
00014                 e = elist[i]; w = wg.weight(e); p = i;
00015                 while (1) {
00016                         c = p << 1;
00017                         if (c > wg.m()) break;
00018                         if (c+1 <= wg.m() &&
00019                             wg.weight(elist[c+1]) >= wg.weight(elist[c]))
00020                                 c++;
00021                         if (wg.weight(elist[c]) <= w) break;
00022                         elist[p] = elist[c]; p = c;
00023                 }
00024                 elist[p] = e;
00025         }
00026         // now edges are in heap-order with largest weight edge on top
00027 
00028         for (i = wg.m()-1; i >= 1; i--) {
00029                 e = elist[i+1]; elist[i+1] = elist[1];
00030                 // now largest edges in positions wg.m(), wg.m()-1,..., i+1
00031                 // edges in 1,...,i form a heap with largest weight edge on top
00032                 // pushdown from 1
00033                 w = wg.weight(e); p = 1;
00034                 while (1) {
00035                         c = p << 1;
00036                         if (c > i) break;
00037                         if (c+1 <= i &&
00038                             wg.weight(elist[c+1]) >= wg.weight(elist[c]))
00039                                 c++;
00040                         if (wg.weight(elist[c]) <= w) break;
00041                         elist[p] = elist[c]; p = c;
00042                 }
00043                 elist[p] = e;
00044         }
00045 }
00046 
00054 void setupHeap(edge *elist, const Wgraph& wg) {
00055         int i, p, c; edge e; weight w;
00056         i = 1;
00057         for (e = wg.first(); e != 0; e = wg.next(e)) elist[i++] = e;
00058 
00059         for (i = wg.m()/2; i >= 1; i--) {
00060                 // do pushdown starting at i
00061                 e = elist[i]; w = wg.weight(e); p = i;
00062                 while (1) {
00063                         c = 2*p;
00064                         if (c > wg.m()) break;
00065                         if (c+1 <= wg.m() &&
00066                             wg.weight(elist[c+1]) < wg.weight(elist[c]))
00067                                 c++;
00068                         if (wg.weight(elist[c]) >= w) break;
00069                         elist[p] = elist[c]; p = c;
00070                 }
00071                 elist[p] = e;
00072         }
00073 }
00074 
00081 int deleteMin(edge *elist, int last, const Wgraph& wg) {
00082         if (last < 1) return 0;
00083         int result = elist[1]; edge e = elist[last];
00084         weight w = wg.weight(e);
00085         vertex c, p; p = 1;
00086         while (1) {
00087                 c = 2*p;
00088                 if (c > last-1) break;
00089                 if (c+1 < last && wg.weight(elist[c+1]) < wg.weight(elist[c]))
00090                         c++;
00091                 if (wg.weight(elist[c]) >= w) break;
00092                 elist[p] = elist[c]; p = c;
00093         }
00094         elist[p] = e;
00095         return result;
00096 }
00097 
00098 // Find a minimum spanning tree of wg using Kruskal's algorithm and
00099 // return it in mstree.
00100 void kruskal(Wgraph& wg, Wgraph& mstree,
00101              uint32_t& setupTime, uint32_t& treeTime,
00102              int& numLoops,
00103              long long int& findCount, int noOpt) {
00104         uint32_t t1 = Util::getTime();
00105         edge e, e1; vertex u,v,cu,cv; weight w;
00106         edge *elist = new edge[wg.m()+1];
00107         setupHeap(elist,wg);
00108         uint32_t t2 = Util::getTime();
00109         Partition vsets(wg.n(),noOpt);
00110         int k = 0; int i = 0;
00111         while (k < wg.n()-1) {
00112                 e = deleteMin(elist,wg.m()-(i++),wg);
00113                 u = wg.left(e); v = wg.right(e); w = wg.weight(e);
00114                 cu = vsets.find(u); cv = vsets.find(v);
00115                 if (cu != cv) {
00116                         vsets.link(cu,cv);
00117                         e = mstree.join(u,v); mstree.setWeight(e,w);
00118                         k++;
00119                 }
00120         }
00121         numLoops = i;
00122         uint32_t t3 = Util::getTime();
00123         setupTime = t2-t1; treeTime = t3-t2; findCount = vsets.findcount();
00124 }
00125 
00126 void kruskal(Wgraph& wg, List& mstree) {
00127 // Find a minimum spanning tree of wg using Kruskal's algorithm and
00128 // return it in mstree. This version returns a list of the edges using
00129 // the edge numbers in wg, rather than a separate Wgraph data structure.
00130         edge e, e1; vertex u,v,cu,cv; weight w;
00131         Partition vsets(wg.n());
00132         edge *elist = new edge[wg.m()+1];
00133         int i = 1;
00134         for (e = wg.first(); e != 0; e = wg.next(e)) elist[i++] = e;
00135         sortEdges(elist,wg);
00136         for (e1 = wg.first(); e1 != 0; e1 = wg.next(e1)) {
00137                 e = elist[e1];
00138                 u = wg.left(e); v = wg.right(e); w = wg.weight(e);
00139                 cu = vsets.find(u); cv = vsets.find(v);
00140                 if (cu != cv) {
00141                          vsets.link(cu,cv); mstree.addLast(e);
00142                 }
00143         }
00144 }
 All Classes Files Functions Variables Typedefs Friends