使用堆排序,并查集实现kruskal算法。
堆排序算法见:http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html
并查集合:http://www.cnblogs.com/cherish_yimi/archive/2009/10/11/1580839.html
#include "iostream" #include "vector" #include "fstream" using namespace std; struct edge { int u; int v; int weight; }; std::vector<edge> E;//边的数组 std::vector<int> rank;//秩,树的最大高度 std::vector<int> father;//父亲节点 int vertexnum;//节点数 int edgenum;//边数 void make_set(int x);// 初始化集合 void swap(edge *a,edge *b);//交换边 void initialvector(){// 初始化 E.resize(edgenum); rank.resize(vertexnum,0); father.resize(vertexnum); for(int i = 0;i < vertexnum;i++){ make_set(i); } } void getData(){//获取数据 ifstream in("data"); in>>vertexnum>>edgenum; initialvector(); int from,to; double w; int i = 0; while(in>>from>>to>>w){ E[i].u = from; E[i].v = to; E[i].weight = w; i++; } } void HeapAdjust(int i,int size){ int lchild = 2*i + 1;//i的左孩子节点序号 int rchild = 2*i + 2;//i的右孩子节点序号 int min = i; if(i < size/2){//如果i是叶节点就不用进行调整 if(lchild < size && E[lchild].weight < E[min].weight){ min = lchild; } if(rchild < size && E[rchild].weight < E[min].weight){ min = rchild; } if(min != i){ swap(&E[i],&E[min]); HeapAdjust(min,size);//重新调整被破坏的堆 } } } void swap(edge *a,edge *b){ edge temp; temp = *a; *a = *b; *b = temp; } void make_heap(){ for(int i = edgenum/2 -1;i>=0;i--){ HeapAdjust(i,edgenum); } } edge minedge(int &m){ swap(E[0],E[m]); HeapAdjust(0,--m); return E[m+1]; } void make_set(int x){ father[x] = x; } int find_set(int x){// 查找x元素所在的集合,回溯时压缩路径 if(x != father[x]){ father[x] = find_set(father[x]); } return father[x]; } /* 按秩合并x,y所在的集合 下面的那个if else结构不是绝对的,具体根据情况变化 但是,宗旨是不变的即,按秩合并,实时更新秩。 */ void unionset(int x,int y){ x = find_set(x); y = find_set(y); if(x == y) return; if(rank[x] > rank[y]){ father[y] = x ; }else{ if(rank[x] == rank[y]){ rank[y]++; } father[x] = y; } } int main(int argc, char const *argv[]) { getData(); int u,v,i = 0; int m = edgenum - 1; std::vector<edge> minset; edge min_edge; make_heap(); while(i < edgenum-1 && m > 0){ min_edge = minedge(m); u = find_set(min_edge.u); v = find_set(min_edge.v); if(u != v){ unionset(u,v); minset.push_back(min_edge); cout<<min_edge.u<<"->"<<min_edge.v<<"\t"<<min_edge.weight<<endl; i++; } } }
7 11
0 1 7
0 3 5
1 2 8
1 3 9
1 4 7
2 4 5
3 4 15
3 5 6
4 5 8
4 6 9
5 6 11
参考:http://www.cnblogs.com/cherish_yimi/archive/2009/10/11/1580839.html
http://www.slyar.com/blog/kruskal-disjoint-sets-c.html
http://www.cnblogs.com/dolphin0520/archive/2011/10/06/2199741.html