Пример #1
0
        /// <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;
                }
            }
        }
Пример #2
0
 public int CompareTo(FullNode <K, V> other) => this.Key.CompareTo(other.Key);
Пример #3
0
        /// <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);
        }