/** * Kruskal's spanning tree algorithm with union-find * Skiena: The Algorithm Design Manual, p. 196ff * Note: the sites are implied: they consist of the end points of the line segments */ public static List <LineSegment> Kruskal(List <LineSegment> lineSegments, KruskalType type = KruskalType.MINIMUM) { Dictionary <Nullable <Vector2>, Node> nodes = new Dictionary <Nullable <Vector2>, Node>(); List <LineSegment> mst = new List <LineSegment>(); Stack <Node> nodePool = Node.pool; switch (type) { // note that the compare functions are the reverse of what you'd expect // because (see below) we traverse the lineSegments in reverse order for speed case KruskalType.MAXIMUM: lineSegments.Sort(delegate(LineSegment l1, LineSegment l2) { return(LineSegment.CompareLengths(l1, l2)); }); break; default: lineSegments.Sort(delegate(LineSegment l1, LineSegment l2) { return(LineSegment.CompareLengths_MAX(l1, l2)); }); break; } for (int i = lineSegments.Count; --i > -1;) { LineSegment lineSegment = lineSegments[i]; Node node0 = null; Node rootOfSet0; if (!nodes.ContainsKey(lineSegment.p0)) { node0 = nodePool.Count > 0 ? nodePool.Pop() : new Node(); // intialize the node: rootOfSet0 = node0.parent = node0; node0.treeSize = 1; nodes[lineSegment.p0] = node0; } else { node0 = nodes[lineSegment.p0]; rootOfSet0 = Find(node0); } Node node1 = null; Node rootOfSet1; if (!nodes.ContainsKey(lineSegment.p1)) { node1 = nodePool.Count > 0 ? nodePool.Pop() : new Node(); // intialize the node: rootOfSet1 = node1.parent = node1; node1.treeSize = 1; nodes[lineSegment.p1] = node1; } else { node1 = nodes[lineSegment.p1]; rootOfSet1 = Find(node1); } if (rootOfSet0 != rootOfSet1) { // nodes not in same set mst.Add(lineSegment); // merge the two sets: int treeSize0 = rootOfSet0.treeSize; int treeSize1 = rootOfSet1.treeSize; if (treeSize0 >= treeSize1) { // set0 absorbs set1: rootOfSet1.parent = rootOfSet0; rootOfSet0.treeSize += treeSize1; } else { // set1 absorbs set0: rootOfSet0.parent = rootOfSet1; rootOfSet1.treeSize += treeSize0; } } } foreach (Node node in nodes.Values) { nodePool.Push(node); } return(mst); }
public static List <LineSegment> Kruskal(List <LineSegment> lineSegments, KruskalType type = KruskalType.MINIMUM) { Dictionary <Vector2?, Node> dictionary = new Dictionary <Vector2?, Node>(); List <LineSegment> list = new List <LineSegment>(); Stack <Node> pool = Node.pool; if (type == KruskalType.MAXIMUM) { lineSegments.Sort((LineSegment l1, LineSegment l2) => LineSegment.CompareLengths(l1, l2)); } else { lineSegments.Sort((LineSegment l1, LineSegment l2) => LineSegment.CompareLengths_MAX(l1, l2)); } int num = lineSegments.Count; while (--num > -1) { LineSegment lineSegment = lineSegments[num]; Node node = null; Node node2; if (!dictionary.ContainsKey(lineSegment.p0)) { node = ((pool.Count <= 0) ? new Node() : pool.Pop()); node2 = (node.parent = node); node.treeSize = 1; dictionary[lineSegment.p0] = node; } else { node = dictionary[lineSegment.p0]; node2 = Find(node); } Node node3 = null; Node node4; if (!dictionary.ContainsKey(lineSegment.p1)) { node3 = ((pool.Count <= 0) ? new Node() : pool.Pop()); node4 = (node3.parent = node3); node3.treeSize = 1; dictionary[lineSegment.p1] = node3; } else { node3 = dictionary[lineSegment.p1]; node4 = Find(node3); } if (node2 != node4) { list.Add(lineSegment); int treeSize = node2.treeSize; int treeSize2 = node4.treeSize; if (treeSize >= treeSize2) { node4.parent = node2; node2.treeSize += treeSize2; } else { node2.parent = node4; node4.treeSize += treeSize; } } } foreach (Node value in dictionary.Values) { pool.Push(value); } return(list); }