... ... // 升序遍历 for (i = 0; i < G.numEdges; i++) { n = Find(parent, edges[i].begin); m = Find(parent, edges[i].end); // 判断两个分量是否同属一个 if (n != m) { parent[n] = m; } } }
intFind(int*parent, intf) { // 遍历分量 while (parent[f] > 0) { f = parent[f]; }
return f; }
查找优化
针对并查集中查找元素根节点函数Find有2种优化方式:
路径压缩(path compression)
路径减半(path halving)
路径压缩
其实现方式是将树结构压平,使得子节点指针均指向根节点,这样能够加快元素的查询操作
1 2 3 4
function Find(x) ifx.parent != x x.parent := Find(x.parent) returnx.parent
路径减半
其实现方式是将节点父指针指向祖父节点
1 2 3 4 5
function Find(x) whilex.parent != x x.parent := x.parent.parent x := x.parent returnx
function Union(x, y) xRoot := Find(x) yRoot := Find(y)
// x and y are already in the same set if xRoot == yRoot return
// x and y are not in same set, so we merge them if xRoot.rank < yRoot.rank xRoot, yRoot := yRoot, xRoot // swap xRoot and yRoot // merge yRoot into xRoot yRoot.parent := xRoot if xRoot.rank == yRoot.rank: xRoot.rank := xRoot.rank + 1
voidAdjacencyTableUndirectedGraph::MiniSpanTree_Kruskal(GraphAdjList G){ int i, j, k, n, m; EdgeNode *e; std::array<Edge, MAXEDGE> edges = {}; DisjointSet disjointSet(G.numVertexes);
// 将边集赋值给edges k = 0; for (i = 0; i < G.numVertexes; i++) { e = G.adjList[i].firstEdge;
while (e != nullptr) { if (e->adjvex > i) { Edge edge; edge.begin = i; edge.end = e->adjvex; edge.weight = e->weight;