コード例 #1
0
        /// <summary>Continues cutting the tree in two, assuming that child nodes have been handled.</summary>
        private static void PartitionUpwardToParentSideOf(NestingDepthTreeNode n, int d, NestingDepthTreeNode orphan)
        {
            if (n == null) return;
            n.RecomputeAggregates();

            var p = n._parent;
            if (n.DirToParent() == d) {
                // going from n to p crosses the cut line, so we must disconnect them
                n._parent = null;

                // the orphan node takes n's place
                p.SetChild(-d, orphan);
                if (orphan != null) orphan._parent = p;

                // switch directions back towards the cut, and onward with our new orphan n!
                PartitionUpwardToParentSideOf(p, -d, n);
            } else {
                // didn't pass over the cut line, keep going upwards
                PartitionUpwardToParentSideOf(p, d, orphan);
            }
        }
コード例 #2
0
        public static IncludeResult IncludeHelper(NestingDepthTreeNode root, int index, int adjust, int refAdjust)
        {
            // Do we need to create a new node?
            if (root == null) {
                return new IncludeResult(new NestingDepthTreeNode(index, adjust, refAdjust));
            }

            // It is understood that the caller will fixup our parent afterwards; we must act independently of the tree above us
            root._parent = null;

            // Is this node the one we need to adjust?
            if (index == root._offset) {
                root._adjust += adjust;
                root._refCount += refAdjust;
                root.RecomputeAggregates();

                // nodes can be removed when they are not referenced and have no effect on the totals
                if (root._adjust == 0 && root._refCount == 0) {
                    return new IncludeResult(null, root.Implode());
                }

                return new IncludeResult(root);
            }

            // Pick the subtree the node has to end up and recurse the inclusion that-a-way
            var d = index.CompareTo(root._offset);
            var subtree = root.Child(d);
            var preTotal = GetTotalAdjust(subtree);
            var subResult = IncludeHelper(subtree, index, adjust, refAdjust);
            var postTotal = GetTotalAdjust(subResult.NewRoot);
            if (preTotal + adjust != postTotal) {
                throw new InvalidOperationException("Invariant violated: total adjustment did not shift by the included adjustment.");
            }

            // Great! Now we just need to fixup so the new subtree is linked in
            var c = subResult.NewRoot;
            root.SetChild(d, c);
            if (c != null) c._parent = root;
            root.RecomputeAggregates();

            // Oh, and do a token effort to keep things balanced using our hacky hierarchical ordering over the indexes
            // Can we get away with not rotating the new child above ourselves to keep things sorta balanced?
            if (c == null || !c.ShouldBeParentOf(root)) {
                return new IncludeResult(subResult.AdjustedNode, root);
            }

            // darn, need to rotate
            var s = c.Child(-d);
            c.SetChild(-d, root);
            root.SetChild(d, s);

            // fixup
            c._parent = null;
            root._parent = c;
            if (s != null) s._parent = root;
            root.RecomputeAggregates();
            c.RecomputeAggregates();

            // finally
            return new IncludeResult(subResult.AdjustedNode, c);
        }