Grafalgo
Library of useful data structures and algorithms
|
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 }