/// <summary> /// Creates a demotion path from a chain of demotions done at path /// </summary> /// <returns>New root of the tree</returns> private Node <K, V> MoveDemotionUp(List <FullNode <K, V> > path) { // Value of previous node after demotion var lastrank = -1; if (path[0].Left != null || path[0].Right == null) { } else { lastrank = Math.Min(path[0].Right.rank, path[0].Left.rank); } for (int i = 0; i < path.Count; i++) { var current = path[i]; if (current.Promoted) { // Special leaf case first if (path[i].Left == null && path[i].Right == null) { DeleteFromPromotionPath(path, 0); path[0].Base.rank = 0; if (path.Count == 1) { return(path[0].Base); } path.RemoveAt(0); lastrank = 0; continue; } if (current.Rank - lastrank == 2) { FinishDemotionPath(i - 1); // Remove from promotion path and end DeleteFromPromotionPath(path, i); return(path.Last().Base); } else { DemoteWithChild(i - 1); // Rotation will be needed. FinishDemotionPath(i - 2); DeleteFromPromotionPath(path, i); return(PickRotationDemote(path, i)); } } else if (current.Demoted == 2) { // Must be at least rank 2 // Must have come from 3-son DemoteWithChild(i - 1); FinishDemotionPath(i - 2); DeleteFromDemotionPath(path, i); return(PickRotationDemote(path, i)); } else if (current.Demoted == 1) { // Special leaf case first if (path[i].Left == null && path[i].Right == null) { DeleteFromDemotionPath(path, 0); path[0].Base.rank = 0; if (path.Count == 1) { return(path[0].Base); } path.RemoveAt(0); lastrank = 0; continue; } if (current.Rank == lastrank + 2) { FinishDemotionPath(i - 1); // 1-son was demoted DeleteFromDemotionPath(path, i); return(path.Last().Base); } else { // 3-son is marked // Examine children of 1-child var(l, r) = GetTypeOf1ChildVertex(current.Base); if (r == l && r + 2 == current.Rank) { // Second demote here lastrank = current.Rank - 1; continue; } else if (i == 0) { // Rotation DeleteFromDemotionPath(path, 0); return(PickRotationDemote(path, 0)); } else { // Rotation DemoteWithChild(i - 1); FinishDemotionPath(i - 2); DeleteFromDemotionPath(path, i); return(PickRotationDemote(path, i)); } } } else if (current.RankDecreasedByParent) { FinishDemotionPath(i - 1); DeleteFromDemotionPath(path, i + 1); return(path.Last().Base); } else if (path[i].Left == null && path[i].Right == null) { path[0].Base.rank = 0; if (path.Count == 1) { return(path[0].Base); } path.RemoveAt(0); lastrank = 0; continue; } else if (current.Rank == lastrank + 3) { var(l, r) = GetTypeOf1ChildVertex(current.Base); if (current.Rank - l == 2 || current.Rank - r == 2) { // Rotate DemoteWithChild(i - 1); FinishDemotionPath(i - 2); return(PickRotationDemote(path, i)); } else { // Demote lastrank = current.Rank - 1; continue; } } else { // Invariant holds FinishDemotionPath(i - 1); return(path.Last().Base); } } // Top of the path has been reached FinishDemotionPath(path.Count - 1); return(path.Last().Base); (int r, int l) GetTypeOf1ChildVertex(Node <K, V> node) { Node <K, V> onechild; if (node.Left != null && node.Left.RankWithOwnOffset > lastrank) { onechild = node.Left; } else { onechild = node.Right; } int r = -1, l = -1; if (onechild.Right != null) { r = onechild.Right.RankWithOwnOffset; } if (onechild.Left != null) { l = onechild.Left.RankWithOwnOffset; } if (onechild.PromotionStart) { if (onechild.ModPathEnd > onechild) { r++; } else { l++; } } if (onechild.DemotionStart) { if (onechild.ModPathEnd > onechild) { r++; } else { l++; } } if (onechild.DemotionStart2) { if (onechild.ModPathEnd2 > onechild) { r++; } else { l++; } } return(r, l); } void DemoteWithChild(int index) { if (index < 0) { return; } FullNode <K, V> node = path[index]; Node <K, V> onechild = null; if (node.Demoted == 1) { // Demoted == 1 DeleteFromDemotionPath(path, index); } if (node.Left != null && node.Left.RankWithOwnOffset + 1 == node.Rank) { onechild = node.Left; } if (node.Right != null && node.Right.RankWithOwnOffset + 1 == node.Rank) { onechild = node.Right; } if (onechild != null) { onechild.rank--; } node.Base.rank--; } void FinishDemotionPath(int pos) { if (pos < 0) { return; } if (pos == 0) { path[0].Base.rank--; if (path[0].Base.Left.rank == path[0].Rank) { path[0].Base.Left.rank--; } if (path[0].Base.Right.rank == path[0].Rank) { path[0].Base.Right.rank--; } return; } for (int i = 0; i <= pos; i++) { if (path[i].Demoted == 1) { path[i].PathStart2 = path[pos]; path[i].DemotedChild = true; } else { path[i].PathStart = path[pos]; path[i].DemotedChild = (path[i].Base.Right?.rank == path[i].Rank) || (path[i].Base.Left?.rank == path[i].Rank); } path[i].Demoted++; } if (path[pos].Base.ModPathEnd != null) { path[pos].Base.ModPathEnd2 = path[0].Base; path[pos].Base.DemotionStart2 = true; } else { path[pos].Base.ModPathEnd = path[0].Base; path[pos].Base.DemotionStart = true; } } }
public int CompareTo(FullNode <K, V> other) => this.Key.CompareTo(other.Key);
/// <summary> /// Descend from the root and locate a vertex with the given key. /// </summary> /// <returns>List of vertices on the path</returns> public List <FullNode <K, V> > GetPath(K Key) { List <FullNode <K, V> > nodes = new List <FullNode <K, V> >(); var current = Root; int demoting = 0; bool promoting = false; Node <K, V> bottom = null, bottom2 = null; FullNode <K, V> top = null, top2 = null; bool demotechild = false; while (current != null) { var v = new FullNode <K, V>(current); nodes.Add(v); if (current.PromotionStart) { promoting = true; bottom = current.ModPathEnd; top = v; } if (current.DemotionStart) { demoting++; if (demoting == 1) { bottom = current.ModPathEnd; top = v; } else { bottom2 = current.ModPathEnd; top2 = v; } } if (current.DemotionStart2) { demoting++; if (demoting == 1) { bottom = current.ModPathEnd; top = v; } else { bottom2 = current.ModPathEnd2; top2 = v; } } v.Demoted = demoting; v.Promoted = promoting; v.PathStart = top; v.PathStart2 = top2; v.RankDecreasedByParent = demotechild; // Identify demoted child: // This applies even to doubly demoted vertices if (demoting > 1) { if (bottom.Key.CompareTo(current.Key) > 0) { v.DemotedChild = (current.rank - current.Left.rank == 1); demotechild = Key.CompareTo(current.Key) > 0; } else { v.DemotedChild = (current.rank - current.Right.rank == 1); demotechild = Key.CompareTo(current.Key) < 0; } } else { demotechild = false; } if (Key.CompareTo(current.Key) < 0) { if (bottom2 != null && bottom2.Key.CompareTo(current.Key) >= 0) { bottom2 = null; demoting--; } if (bottom != null && bottom.Key.CompareTo(current.Key) >= 0) { bottom = bottom2; bottom2 = null; demoting--; promoting = false; } current = current.Left; } else { if (bottom2 != null && bottom2.Key.CompareTo(current.Key) <= 0) { bottom2 = null; demoting--; } if (bottom != null && bottom.Key.CompareTo(current.Key) <= 0) { bottom = bottom2; bottom2 = null; demoting--; promoting = false; } current = current.Right; } } return(nodes); }