/**
         *  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);
        }
Example #2
0
        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);
        }