Exemplo n.º 1
0
        /// <summary>
        /// Find all cells inside the given range.
        /// </summary>
        /// <returns>The range.</returns>
        /// <param name="start">Start.</param>
        /// <param name="end">End.</param>
        public CellTreeNode[] GetRange(double start, double end)
        {
            List <CellTreeNode> cells = new List <CellTreeNode>();

            CellTreeNode cell = FindAboveOrEqualTo(start);

            while (cell != null && cell.Cell.Position <= end)
            {
                cells.Add(cell);

                cell = cell.Next();
            }

            return(cells.ToArray());
        }
Exemplo n.º 2
0
        public IEnumerator GetEnumerator()
        {
            CellTreeNode node = Min;

            if (node == null)
            {
                yield break;
            }

            while (node != null)
            {
                yield return(node.Cell);

                node = node.Next();
            }

            yield break;
        }
Exemplo n.º 3
0
        public CellTree Remove(CellTreeNode node)
        {
            CellTreeNode nodeToDeleteAfterwards = null;

            if (node == Min)
            {
                Min = node.Next();
            }
            else if (node == Max)
            {
                Max = node.Prev();
            }

            if (node.Left == null && node.Right == null)
            {
                if (Root == node)
                {
                    Root = null;
                    Min  = null;
                    Max  = null;
                    return(this);
                }

                if (node.IsRed)
                {
                    Replace(node, null);
                    return(this);
                }

                // black node with no children, not root

                // we will delete the node afterwards. it's a 'phantom' leaf.
                nodeToDeleteAfterwards = node;
                // do we need to track the actual node, as it may be changed by a rule?
            }
            else if (node.Left != null && node.Right != null)
            {
                // we find the left-most child of right side and copy it's value to the node being deleted
                // The node that we copied from (left-most) can then by deleted because it
                // has at most 1 non-leaf child.

                var succesor = node.Left;
                while (succesor.Right != null)
                {
                    succesor = succesor.Right;
                }

                // copy data from succesor node
                succesor.CopyTo(node);

                //Swap(node, succesor);

                return(Remove(succesor));
            }

            if (node.Left != null || node.Right != null)
            {
                // one child is a non-leaf

                var child = node.Left ?? node.Right;


                if (!node.IsRed && child.IsRed)
                {
                    // black node, red child
                    Replace(node, child);

                    child.IsRed = false;
                    return(this);
                }

                if (node.IsRed && !child.IsRed)
                {
                    // red node, black child
                    Replace(node, child);
                    return(this);
                }


                // black node with black child
                Replace(node, child);
                node = child;
            }

            while (true)
            {
                // node is now a "double black" node

                if (node == Root)
                {
                    break;                     // case 1. terminal case
                }

                var sibling = node.GetSibling();

                if (sibling.IsRed)
                {
                    // case 2
                    // node is black, has black parent, and a red sibling
                    // make sibling take the place of the parent.
                    if (node.Parent.Left == node)
                    {
                        RotateLeft(node.Parent);
                    }
                    else
                    {
                        RotateRight(node.Parent);
                    }

                    node.Parent.IsRed = true;
                    sibling.IsRed     = false;
                    sibling           = node.GetSibling();
                }

                else if (!node.Parent.IsRed && !sibling.IsRed && (sibling.Left == null || !sibling.Left.IsRed) && (sibling.Right == null || !sibling.Right.IsRed))
                {
                    // case 3
                    // node is black, black parent, black sibling with black children

                    sibling.IsRed = true;

                    node = node.Parent;
                    // go to start with parent as new node. (we pushed the double black status up to the parent)
                    continue;
                }

                else if (node.Parent.IsRed && (sibling.Left == null || !sibling.Left.IsRed) && (sibling.Right == null || !sibling.Right.IsRed))
                {
                    // case 4, terminal case
                    node.Parent.IsRed = false;
                    sibling.IsRed     = true;
                    break;
                }

                else if (!sibling.IsRed && node.HasSiblingWithInnerRedChild())
                {
                    // case 5
                    // black node, black parent, black sibling with inner red child
                    if (node.Parent.Left == node)
                    {
                        RotateRight(sibling);
                        sibling.Left.IsRed = false;
                    }
                    else
                    {
                        RotateLeft(sibling);
                        sibling.Right.IsRed = false;
                    }

                    sibling.IsRed = true;
                    sibling       = node.GetSibling();
                }

                if (!sibling.IsRed && node.HasSiblingWithOuterRedChild())
                {
                    // case 6, terminal case
                    // black node, don't care parent's color, black sibling with outer red child and inner child with either color.
                    if (node.Parent.Left == node)
                    {
                        RotateLeft(node.Parent);
                        sibling.Right.IsRed = false;
                    }
                    else
                    {
                        RotateRight(node.Parent);
                        sibling.Left.IsRed = false;
                    }

                    sibling.IsRed     = node.Parent.IsRed;
                    node.Parent.IsRed = false;

                    // node is no longer a bouble black.
                    break;
                }
            }

            if (nodeToDeleteAfterwards != null)
            {
                Replace(nodeToDeleteAfterwards, null);
            }

            Count--;

            return(this);
        }