예제 #1
0
        public void TestRemove()
        {
            var tree = new RBTree <int>();

            for (var i = 0; i < 500; i++)
            {
                tree.InsertSuccessor(RBTree <int> .GetLast(tree.Root), i);
                for (var j = 0; j <= i; j++)
                {
                    var traverse = RBTree <int> .GetFirst(tree.Root);

                    for (var k = 0; k < j; k++)
                    {
                        traverse = traverse.Next;
                    }
                    //remove jth element
                    tree.RemoveNode(traverse);
                    var check = RBTree <int> .GetFirst(tree.Root);

                    for (var k = 0; k < j; k++)
                    {
                        Assert.AreEqual(k, check.Data);
                        check = check.Next;
                    }
                    for (var k = j; k < i; k++)
                    {
                        Assert.AreEqual(k + 1, check.Data);
                        check = check.Next;
                    }
                    //readd
                    tree.InsertSuccessor(traverse.Previous, traverse.Data);
                }
            }
        }
예제 #2
0
        public void TestSuccessorOrder()
        {
            var tree = new RBTree <int>();

            tree.InsertSuccessor(null, 1);
            tree.InsertSuccessor(tree.Root, 2);
            tree.InsertSuccessor(tree.Root.Right, 3);
            Assert.AreEqual(2, tree.Root.Data);
            Assert.AreEqual(1, tree.Root.Left.Data);
            Assert.AreEqual(3, tree.Root.Right.Data);
            Assert.AreEqual(tree.Root, tree.Root.Left.Next);
            Assert.AreEqual(tree.Root.Left, tree.Root.Previous);
            Assert.AreEqual(tree.Root, tree.Root.Right.Previous);
            Assert.AreEqual(tree.Root.Right, tree.Root.Next);
        }
예제 #3
0
        public void TestInsertInMiddle()
        {
            var tree  = new RBTree <int>();
            var first = tree.InsertSuccessor(null, 1);

            tree.InsertSuccessor(first, -1);
            tree.InsertSuccessor(first, 2);
            Assert.AreEqual(2, tree.Root.Data);
            Assert.AreEqual(1, tree.Root.Left.Data);
            Assert.AreEqual(-1, tree.Root.Right.Data);
            first = RBTree <int> .GetFirst(tree.Root);

            Assert.AreEqual(1, first.Data);
            first = first.Next;
            Assert.AreEqual(2, first.Data);
            first = first.Next;
            Assert.AreEqual(-1, first.Data);
            first = first.Next;
            Assert.AreEqual(null, first);
        }
예제 #4
0
        public void TestInsertAtBack()
        {
            var tree = new RBTree <char>();
            var last = tree.InsertSuccessor(null, 'L');

            last = tree.InsertSuccessor(last, 'o');
            last = tree.InsertSuccessor(last, 'g');
            last = tree.InsertSuccessor(last, 'a');
            last = tree.InsertSuccessor(last, 'n');
            last = tree.InsertSuccessor(last, '!');
            Assert.AreEqual('o', tree.Root.Data);
            Assert.AreEqual('L', tree.Root.Left.Data);
            Assert.AreEqual('a', tree.Root.Right.Data);
            Assert.AreEqual('g', tree.Root.Right.Left.Data);
            Assert.AreEqual('n', tree.Root.Right.Right.Data);
            Assert.AreEqual('!', tree.Root.Right.Right.Right.Data);
            var traverse = RBTree <char> .GetFirst(tree.Root);

            Assert.AreEqual('L', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual('o', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual('g', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual('a', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual('n', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual('!', traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual(null, traverse);
        }
예제 #5
0
        public void TestInsertAtFront()
        {
            var tree = new RBTree <int>();

            tree.InsertSuccessor(null, 4);
            tree.InsertSuccessor(null, 5);
            tree.InsertSuccessor(null, 3);
            tree.InsertSuccessor(null, 4);
            Assert.AreEqual(5, tree.Root.Data);
            Assert.AreEqual(4, tree.Root.Right.Data);
            Assert.AreEqual(3, tree.Root.Left.Data);
            Assert.AreEqual(4, tree.Root.Left.Left.Data);
            var traverse = RBTree <int> .GetFirst(tree.Root);

            Assert.AreEqual(4, traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual(3, traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual(5, traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual(4, traverse.Data);
            traverse = traverse.Next;
            Assert.AreEqual(null, traverse);
        }
예제 #6
0
        public void TestRemoveInMiddle()
        {
            var tree = new RBTree <char>();
            var last = tree.InsertSuccessor(null, 'L');

            last = tree.InsertSuccessor(last, 'o');
            var mid = last = tree.InsertSuccessor(last, 'g');

            last = tree.InsertSuccessor(last, 'a');
            last = tree.InsertSuccessor(last, 'n');
            last = tree.InsertSuccessor(last, '!');

            tree.RemoveNode(mid);
            Assert.AreEqual('o', tree.Root.Data);
            Assert.AreEqual('L', tree.Root.Left.Data);
            Assert.AreEqual('n', tree.Root.Right.Data);
            Assert.AreEqual('a', tree.Root.Right.Left.Data);
            Assert.AreEqual('!', tree.Root.Right.Right.Data);
        }
예제 #7
0
        public void TestRemoveAtBack()
        {
            var tree = new RBTree <char>();
            var last = tree.InsertSuccessor(null, 'L');

            last = tree.InsertSuccessor(last, 'o');
            last = tree.InsertSuccessor(last, 'g');
            last = tree.InsertSuccessor(last, 'a');
            last = tree.InsertSuccessor(last, 'n');
            last = tree.InsertSuccessor(last, '!');
            var prev = last.Previous;

            tree.RemoveNode(last);
            last = prev.Previous;
            tree.RemoveNode(prev);
            tree.RemoveNode(last);
            Assert.AreEqual('o', tree.Root.Data);
            Assert.AreEqual('L', tree.Root.Left.Data);
            Assert.AreEqual('g', tree.Root.Right.Data);
        }
예제 #8
0
        public void TestRemoveAtFront()
        {
            var tree  = new RBTree <char>();
            var last  = tree.InsertSuccessor(null, 'L');
            var first = last;

            last = tree.InsertSuccessor(last, 'o');
            last = tree.InsertSuccessor(last, 'g');
            last = tree.InsertSuccessor(last, 'a');
            last = tree.InsertSuccessor(last, 'n');
            last = tree.InsertSuccessor(last, '!');
            last = first.Next;
            tree.RemoveNode(first);
            first = last;
            last  = last.Next;
            tree.RemoveNode(first);
            first = last;
            tree.RemoveNode(first);
            Assert.AreEqual('n', tree.Root.Data);
            Assert.AreEqual('a', tree.Root.Left.Data);
            Assert.AreEqual('!', tree.Root.Right.Data);
        }
예제 #9
0
        internal void AddBeachSection(FortuneSiteEvent siteEvent, MinHeap <FortuneEvent> eventQueue, HashSet <FortuneCircleEvent> deleted, LinkedList <VoronoiEdge> edges)
        {
            var site      = siteEvent.Site;
            var x         = site.X;
            var directrix = site.Y;

            RBTreeNode <BeachSection> leftSection  = null;
            RBTreeNode <BeachSection> rightSection = null;
            var node = beachLine.Root;

            //find the parabola(s) above this site
            while (node != null && leftSection == null && rightSection == null)
            {
                var distanceLeft = LeftBreakpoint(node, directrix) - x;
                if (distanceLeft > 0)
                {
                    //the new site is before the left breakpoint
                    if (node.Left == null)
                    {
                        rightSection = node;
                    }
                    else
                    {
                        node = node.Left;
                    }
                    continue;
                }

                var distanceRight = x - RightBreakpoint(node, directrix);
                if (distanceRight > 0)
                {
                    //the new site is after the right breakpoint
                    if (node.Right == null)
                    {
                        leftSection = node;
                    }
                    else
                    {
                        node = node.Right;
                    }
                    continue;
                }

                //the point lies below the left breakpoint
                if (distanceLeft.ApproxEqual(0))
                {
                    leftSection  = node.Previous;
                    rightSection = node;
                    continue;
                }

                //the point lies below the right breakpoint
                if (distanceRight.ApproxEqual(0))
                {
                    leftSection  = node;
                    rightSection = node.Next;
                    continue;
                }

                // distance Right < 0 and distance Left < 0
                // this section is above the new site
                leftSection = rightSection = node;
            }

            //our goal is to insert the new node between the
            //left and right sections
            var section = new BeachSection(site);

            //left section could be null, in which case this node is the first
            //in the tree
            var newSection = beachLine.InsertSuccessor(leftSection, section);

            //new beach section is the first beach section to be added
            if (leftSection == null && rightSection == null)
            {
                return;
            }

            //main case:
            //if both left section and right section point to the same valid arc
            //we need to split the arc into a left arc and a right arc with our
            //new arc sitting in the middle
            if (leftSection != null && leftSection == rightSection)
            {
                //if the arc has a circle event, it was a false alarm.
                //remove it
                if (leftSection.Data.CircleEvent != null)
                {
                    deleted.Add(leftSection.Data.CircleEvent);
                    leftSection.Data.CircleEvent = null;
                }

                //we leave the existing arc as the left section in the tree
                //however we need to insert the right section defined by the arc
                var copy = new BeachSection(leftSection.Data.Site);
                rightSection = beachLine.InsertSuccessor(newSection, copy);

                //grab the projection of this site onto the parabola
                var y            = ParabolaMath.EvalParabola(leftSection.Data.Site.X, leftSection.Data.Site.Y, directrix, x);
                var intersection = new Point(x, y);

                //create the two half edges corresponding to this intersection
                var leftEdge  = new VoronoiEdge(intersection, site, leftSection.Data.Site);
                var rightEdge = new VoronoiEdge(intersection, leftSection.Data.Site, site);
                leftEdge.Neighbor = rightEdge;

                //put the edge in the list
                edges.AddFirst(leftEdge);

                //store the left edge on each arc section
                newSection.Data.Edge   = leftEdge;
                rightSection.Data.Edge = rightEdge;

                //store neighbors for delaunay
                leftSection.Data.Site.Neighbours.Add(newSection.Data.Site);
                newSection.Data.Site.Neighbours.Add(leftSection.Data.Site);

                //create circle events
                CheckCircle(leftSection, eventQueue);
                CheckCircle(rightSection, eventQueue);
            }

            //site is the last beach section on the beach line
            //this can only happen if all previous sites
            //had the same y value
            else if (leftSection != null && rightSection == null)
            {
                var start   = new Point((leftSection.Data.Site.X + site.X) / 2, double.MinValue);
                var infEdge = new VoronoiEdge(start, leftSection.Data.Site, site);
                var newEdge = new VoronoiEdge(start, site, leftSection.Data.Site);

                newEdge.Neighbor = infEdge;
                edges.AddFirst(newEdge);

                leftSection.Data.Site.Neighbours.Add(newSection.Data.Site);
                newSection.Data.Site.Neighbours.Add(leftSection.Data.Site);

                newSection.Data.Edge = newEdge;

                //cant check circles since they are colinear
            }

            //site is directly above a break point
            else if (leftSection != null && leftSection != rightSection)
            {
                //remove false alarms
                if (leftSection.Data.CircleEvent != null)
                {
                    deleted.Add(leftSection.Data.CircleEvent);
                    leftSection.Data.CircleEvent = null;
                }

                if (rightSection.Data.CircleEvent != null)
                {
                    deleted.Add(rightSection.Data.CircleEvent);
                    rightSection.Data.CircleEvent = null;
                }

                //the breakpoint will dissapear if we add this site
                //which means we will create an edge
                //we treat this very similar to a circle event since
                //an edge is finishing at the center of the circle
                //created by circumscribing the left center and right
                //sites

                //bring a to the origin
                var leftSite = leftSection.Data.Site;
                var ax       = leftSite.X;
                var ay       = leftSite.Y;
                var bx       = site.X - ax;
                var by       = site.Y - ay;

                var rightSite  = rightSection.Data.Site;
                var cx         = rightSite.X - ax;
                var cy         = rightSite.Y - ay;
                var d          = bx * cy - by * cx;
                var magnitudeB = bx * bx + by * by;
                var magnitudeC = cx * cx + cy * cy;
                var vertex     = new Point(
                    (cy * magnitudeB - by * magnitudeC) / (2 * d) + ax,
                    (bx * magnitudeC - cx * magnitudeB) / (2 * d) + ay);

                rightSection.Data.Edge.EndPoint = vertex;

                //next we create a two new edges
                newSection.Data.Edge   = new VoronoiEdge(vertex, site, leftSection.Data.Site);
                rightSection.Data.Edge = new VoronoiEdge(vertex, rightSection.Data.Site, site);

                edges.AddFirst(newSection.Data.Edge);
                edges.AddFirst(rightSection.Data.Edge);

                //add neighbors for delaunay
                newSection.Data.Site.Neighbours.Add(leftSection.Data.Site);
                leftSection.Data.Site.Neighbours.Add(newSection.Data.Site);

                newSection.Data.Site.Neighbours.Add(rightSection.Data.Site);
                rightSection.Data.Site.Neighbours.Add(newSection.Data.Site);

                CheckCircle(leftSection, eventQueue);
                CheckCircle(rightSection, eventQueue);
            }
        }