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); } } }
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); }
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); }
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); }
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); }
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); }
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); }
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); }
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); } }