//-----------------------------------------------------------------------------
//
// Copyright (c) 2010 Nesterovsky Bros. All rights reserved.
//
//
// An immutable AVL tree imlementation.
//
//-----------------------------------------------------------------------------
namespace NesterovskyBros.Collections.AVL
{
using System;
using System.Collections.Generic;
using System.Runtime.Serialization;
using System.Security.Permissions;
///
/// An AVL tree (self-balancing binary search tree).
/// Lookup, insertion, and deletion all take O(log n) time in both
/// the average and worst cases. Additions and deletions may require
/// the tree to be rebalanced by one or more tree rotations.
///
/// The AVL tree is named after its two inventors, G.M. Adelson-Velsky and
/// E.M. Landis, who published it in their 1962 paper
/// "An algorithm for the organization of information."
///
/// Note that tree nodes are immutable and thread safe.
/// Position in a tree is defined by a tree navigator, which is mutable and
/// not safe for threading.
///
/// A node value type.
[Serializable]
public class TreeNavigator:
ICloneable,
ICollection,
IList,
ISerializable
{
///
/// An immutable AVL tree node.
///
/// A node value type.
public class Node
{
///
/// Creates a node instance.
///
/// A node value.
public Node(V value)
{
Size = 1;
Left = null;
Right = null;
Value = value;
}
///
/// Creates a node instance.
///
/// A left child.
/// A right child.
/// A node value.
public Node(Node left, Node right, V value)
{
Size = (left != null ? left.Size : 0) +
(right != null ? right.Size : 0) + 1;
Left = left;
Right = right;
Value = value;
}
///
/// Creates a node instance.
///
/// A left child.
/// A right child.
/// A base node.
public Node(Node left, Node right, Node that)
{
Size = (left != null ? left.Size : 0) +
(right != null ? right.Size : 0) + 1;
Left = left;
Right = right;
Value = that.Value;
}
///
/// A left child node.
///
public readonly Node Left;
///
/// A right child node.
///
public readonly Node Right;
///
/// A size of subtree, including this node.
///
public readonly int Size;
///
/// A node value.
///
public readonly V Value;
}
///
/// Creates a tree navigator instance.
///
public TreeNavigator()
{
}
///
/// Creates a copy of a tree navigator instance.
///
/// An instance to copy.
public TreeNavigator(TreeNavigator that)
{
if ((that != null) && !(that.depth == 0))
{
int depth = that.depth;
var path = ReserveDepth(depth);
var thatPath = that.path;
this.depth = depth;
for(int i = 0; i < path.Length; ++i)
{
if (i >= depth)
{
break;
}
path[i] = thatPath[i];
}
current = that.current;
}
}
///
/// Creates a tree navigator instance.
///
/// A node.
public TreeNavigator(Node node)
{
if (node != null)
{
current = node;
var path = ReserveDepth(1);
depth = 1;
path[0] = node;
}
}
///
/// Creates a clone of this map.
///
/// A serialization info.
/// A streaming context.
protected TreeNavigator(SerializationInfo info, StreamingContext context):
this(Create((V[])info.GetValue("Items", typeof(V[]))))
{
}
#region ICloneable Members
///
/// Creates a clone of this tree navigator.
///
/// A clone of this tree navigator.
public TreeNavigator Clone()
{
return new TreeNavigator(this);
}
///
/// Creates a clone of this tree navigator.
///
/// A clone of this tree navigator.
object ICloneable.Clone()
{
return Clone();
}
#endregion
#region ISerializable Members
///
/// Populates a SerializationInfo with the data needed to serialize
/// the target object.
///
/// A SerializationInfo to populate with data.
/// A destination for this serialization.
[SecurityPermission(SecurityAction.Demand, SerializationFormatter = true)]
void ISerializable.GetObjectData(
SerializationInfo info,
StreamingContext context)
{
V[] items = null;
if (Count > 0)
{
items = new V[Count];
CopyTo(items, 0);
}
info.AddValue("Items", items);
}
#endregion
///
/// Gets node depth.
///
public int Depth
{
get { return depth; }
}
///
/// Get a root node.
///
public Node Root
{
get { return depth <= 1 ? current : path[0]; }
}
///
/// Gets a current node.
///
public Node Current
{
get { return current; }
}
///
/// Gets index of the current node in the tree.
///
public int Index
{
get
{
int index;
if (depth == 0)
{
index = -1;
}
else
{
var path = this.path;
Node parent = path[0];
Node left;
index = 0;
for(int i = 1; i < depth; ++i)
{
Node node = path[i];
if (parent.Right == node)
{
++index;
left = parent.Left;
if (left != null)
{
index += left.Size;
}
}
parent = node;
}
left = parent.Left;
if (left != null)
{
index += left.Size;
}
}
return index;
}
}
///
/// Indicates whether the current node is null.
///
public bool IsNull
{
get { return depth == 0; }
}
///
/// Indicates whether the current node is root of the tree.
///
public bool IsRoot
{
get { return depth == 1; }
}
///
/// Indicates whether there is a parent node for the current node.
///
public bool HasParent
{
get { return depth > 1; }
}
///
/// Indicates whether there is a left child over the current node.
///
public bool HasLeft
{
get { return (current != null) && (current.Left != null); }
}
///
/// Indicates whether there is a right child over the current node.
///
public bool HasRight
{
get { return (current != null) && (current.Right != null); }
}
///
/// Indicates whether there is a predecessor node for a current node.
///
public bool HasPredecessor
{
get
{
bool succeeds = false;
if (depth != 0)
{
var path = this.path;
Node child = null;
for(int i = depth; i-- > 0; )
{
Node node = path[i];
Node left = node.Left;
if ((left != null) && (left != child))
{
succeeds = true;
break;
}
child = node;
}
}
return succeeds;
}
}
///
/// Indicates whether there is a successor node for a current node.
///
public bool HasSuccessor
{
get
{
bool succeeds = false;
if (depth != 0)
{
var path = this.path;
Node child = null;
for(int i = depth; i-- > 0; )
{
Node node = path[i];
Node right = node.Right;
if ((right != null) && (right != child))
{
succeeds = true;
break;
}
child = node;
}
}
return succeeds;
}
}
#region ICollection Members
///
/// Gets a value indicating whether the collection is readonly.
///
public bool IsReadOnly
{
get { return false; }
}
///
/// Adds an item to the collection after the current position.
///
/// A value to add
public void Add(V value)
{
Insert(value, false);
}
///
/// Removes all items from the collection.
///
public void Clear()
{
MoveToNull();
}
///
/// Determines whether the collection contains a specific value.
///
/// A value to locate.
///
/// true if value is found, and false otherwise.
/// If value is found then navigator is positioned to a node with that value.
///
public bool Contains(V value)
{
bool succeeds = false;
if (!IsNull)
{
var comparer = EqualityComparer.Default;
MoveToRoot();
MoveToLeftmost();
do
{
if (comparer.Equals(Current.Value, value))
{
succeeds = true;
break;
}
}
while(MoveToSuccessor());
}
return succeeds;
}
///
/// Copies the elements of the collection to an array, starting at a
/// particular array index.
///
///
/// An array that is the destination of the elements copied
/// from the collection.
///
///
/// An index in array at which copying begins.
///
public void CopyTo(V[] array, int index)
{
if (array == null)
{
throw new ArgumentException("array");
}
if (index < 0)
{
throw new ArgumentException("index");
}
if ((array.Length - index) < Count)
{
throw new ArgumentException("array");
}
if (!IsNull)
{
var navigator = Root.Navigator();
navigator.MoveToLeftmost();
do
{
array[index++] = navigator.Current.Value;
}
while(navigator.MoveToSuccessor());
}
}
///
/// Removes the first occurrence of a specific value from the collection.
///
/// A value to remove.
///
/// true if item was successfully removed from the collection, and false otherwise.
/// This method also returns false if value is not found in the original collection.
///
public bool Remove(V value)
{
bool succeed = false;
if (Contains(value))
{
Remove();
succeed = true;
}
return succeed;
}
///
/// Gets node enumerator.
///
/// A node enumerator.
public IEnumerator GetEnumerator()
{
if (!IsNull)
{
var navigator = Root.Navigator();
navigator.MoveToLeftmost();
do
{
yield return navigator.Current.Value;
}
while(navigator.MoveToSuccessor());
}
}
///
/// Gets a node enumerator.
///
/// A node enumerator.
System.Collections.IEnumerator
System.Collections.IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
#endregion
#region IList Members
///
/// Gets count of nodes in the tree.
///
public int Count
{
get { return depth == 0 ? 0 : path[0].Size; }
}
///
/// Gets or sets the element at the specified index.
///
///
/// A zero-based index of the element to get or set.
///
/// An element at the specified index.
public V this[int index]
{
get
{
if (!MoveToIndex(index))
{
throw new ArgumentOutOfRangeException("index");
}
return Current.Value;
}
set
{
if (!MoveToIndex(index))
{
throw new ArgumentOutOfRangeException("index");
}
Replace(value);
}
}
///
/// Determines the index of a specific item in the list.
///
/// An item to locate.
///
/// An index of item if found in the list, or -1 otherwise.
///
public int IndexOf(V value)
{
return !Contains(value) ? -1 : Index;
}
///
/// Inserts an item to the list at the specified index.
/// Note that index is not accounted but key only.
///
///
/// A zero-based index at which item should be inserted.
///
/// An item to insert.
public void Insert(int index, V item)
{
if (index == Count)
{
if (index > 0)
{
MoveToIndex(index - 1);
}
Insert(item, false);
}
else
{
if (!MoveToIndex(index - 1))
{
throw new ArgumentOutOfRangeException("index");
}
Insert(item, true);
}
}
///
/// Removes a list item at the specified index.
///
///
/// An index of item to remove.
///
public void RemoveAt(int index)
{
if (!MoveToIndex(index))
{
throw new IndexOutOfRangeException("index");
}
Remove();
}
#endregion
///
/// Gets a node in the path.
///
/// A node depth.
/// A node in the node path.
public Node GetPath(int index)
{
return (index >= 0) && (index <= depth) ? path[index] : null;
}
///
/// Moves to the null node.
///
/// always returns true.
public bool MoveToNull()
{
var path = this.path;
for(int i = 0; i < path.Length; ++i)
{
if (i >= depth)
{
break;
}
path[i] = null;
}
depth = 0;
current = null;
return false;
}
///
/// Moves to a tree root, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToRoot()
{
bool succeeds = false;
int depth = this.depth;
if (depth == 1)
{
succeeds = true;
}
else if (depth > 1)
{
var path = this.path;
for(int i = 1; i < path.Length; ++i)
{
if (i >= depth)
{
break;
}
path[i] = null;
}
current = path[0];
this.depth = 1;
succeeds = true;
}
return succeeds;
}
///
/// Moves to a parent node, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToParent()
{
bool succeeds = false;
if (depth > 1)
{
var path = this.path;
path[--depth] = null;
current = path[depth - 1];
succeeds = true;
}
return succeeds;
}
///
/// Moves to a left child node, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToLeft()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
node = node.Left;
if (node != null)
{
var path = this.path;
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = node;
current = node;
succeeds = true;
}
}
return succeeds;
}
///
/// Moves to a right child node, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToRight()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
node = node.Right;
if (node != null)
{
var path = this.path;
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = node;
current = node;
succeeds = true;
}
}
return succeeds;
}
///
/// Moves to the leftmost node of the subtree rooted by the current node,
/// if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToLeftmost()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Node left = node.Left;
if (left != null)
{
var path = this.path;
do
{
node = left;
left = node.Left;
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = node;
}
while(left != null);
current = node;
}
succeeds = true;
}
return succeeds;
}
///
/// Moves to the rightmost node of the subtree rooted by the current node,
/// if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToRightmost()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Node right = node.Right;
if (right != null)
{
var path = this.path;
do
{
node = right;
right = node.Right;
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = node;
}
while(right != null);
current = node;
}
succeeds = true;
}
return succeeds;
}
///
/// Moves to the predecessor node, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToPredecessor()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Node next = node.Left;
var path = this.path;
if (next != null)
{
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = next;
node = next;
next = node.Right;
while(next != null)
{
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = next;
node = next;
next = next.Right;
}
}
else
{
int i = depth;
do
{
if (--i == 0)
{
goto End;
}
next = node;
node = path[i - 1];
}
while(next == node.Left);
while(depth > i)
{
path[--depth] = null;
}
}
current = node;
succeeds = true;
}
End:
return succeeds;
}
///
/// Moves to the successor node, if any.
///
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToSuccessor()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Node next = node.Right;
var path = this.path;
if (next != null)
{
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = next;
node = next;
next = node.Left;
while(next != null)
{
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = next;
node = next;
next = next.Left;
}
}
else
{
int i = depth;
do
{
if (--i == 0)
{
goto End;
}
next = node;
node = path[i - 1];
}
while(next == node.Right);
while(depth > i)
{
path[--depth] = null;
}
}
current = node;
succeeds = true;
}
End:
return succeeds;
}
///
/// Moves to a node with a specified index.
///
/// A node index.
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool MoveToIndex(int index)
{
bool succeeds = false;
if ((index >= 0) && (index < Count))
{
MoveToRoot();
var path = this.path;
Node node = current;
Node next = node.Left;
int i = next != null ? next.Size : 0;
while(index != i)
{
if (index > i)
{
node = node.Right;
next = node.Left;
i += next != null ? next.Size + 1 : 1;
}
else
{
node = node.Left;
next = node.Right;
i -= next != null ? next.Size + 1 : 1;
}
if (path.Length <= depth)
{
path = ReserveDepth(depth + 1);
}
path[depth++] = node;
}
current = node;
succeeds = true;
}
return succeeds;
}
///
/// Insert a new node before or after a specified node.
/// After insertion navigator points to the root of the tree.
/// Use Index property and MoveToIndex() method to navigate to the
/// inserted property.
///
/// A value to insert.
///
/// true to insert before, and false to insert after.
///
///
/// If node has children then tree may be disbalanced.
///
public void Insert(V value, bool before)
{
var path = this.path;
Node node;
if (depth == 0)
{
if (path.Length < 1)
{
path = ReserveDepth(1);
}
node = new Node(value);
path[0] = node;
current = node;
depth = 1;
return;
}
Node parent = current;
if (before)
{
if (parent.Left != null)
{
MoveToPredecessor();
parent = current;
before = false;
}
}
else
{
if (parent.Right != null)
{
MoveToSuccessor();
parent = current;
before = true;
}
}
Node left;
Node right;
if (parent.Size == 1)
{
// This branch is pure allocation optimization.
if (depth == 1)
{
node = before ?
new Node(null, parent, value) :
new Node(parent, null, value);
path[0] = node;
current = node;
return;
}
path[--depth] = null;
Node grand = path[depth - 1];
if (grand.Size == 2)
{
node = new Node(null, null, grand);
node = grand.Left == parent ?
before ?
new Node(new Node(value), node, parent) :
new Node(parent, node, value) :
before ?
new Node(node, parent, value) :
new Node(node, new Node(value), parent);
if (depth == 1)
{
path[0] = node;
current = node;
return;
}
parent = grand;
path[--depth] = null;
grand = path[depth - 1];
}
else
{
node = before ?
new Node(null, parent, value) :
new Node(parent, null, value);
}
current = grand;
left = grand.Left;
if (left == parent)
{
left = node;
right = grand.Right;
}
else
{
right = node;
}
}
else
{
node = new Node(value);
if (before)
{
left = node;
right = parent.Right;
}
else
{
left = parent.Left;
right = node;
}
}
Balance(left, right);
}
///
/// Replaces the current value.
///
/// A new value.
///
/// true if after navigation succeeds, and false otherwise.
/// If navigation succeeds then Current is changed to a new node, otherwise
/// Current is not changed.
///
public bool Replace(V value)
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Replace(new Node(node.Left, node.Right, value));
succeeds = true;
}
return succeeds;
}
///
/// Removes current node from the tree.
/// After remove navigator points to the root of the tree.
/// Use Index property and MoveToIndex() method to navigate to the
/// inserted property.
///
///
/// true if after operation, Current is not null, and false otherwise.
///
public bool Remove()
{
bool succeeds = false;
Node node = current;
if (node != null)
{
Node left = node.Left;
Node right = node.Right;
if ((left != null) && (right != null))
{
RemoveAndBalance();
succeeds = true;
}
else if (depth == 1)
{
// Delete root node.
if (left == null)
{
if (right == null)
{
// Remove last node.
MoveToNull();
}
else
{
path[0] = right;
current = right;
succeeds = true;
}
}
else
{
path[0] = left;
current = left;
succeeds = true;
}
}
else
{
Node parent = path[depth - 2];
if (left == null)
{
if (right == null)
{
// Remove leaf node.
left = parent.Left;
if (left == node)
{
left = null;
right = parent.Right;
}
else
{
right = null;
}
}
else
{
// There is only a right child.
left = parent.Left;
if (left == node)
{
left = right;
right = parent.Right;
}
}
}
else
{
// There is only a left child.
right = parent.Right;
if (right == node)
{
right = left;
left = parent.Left;
}
}
Balance(left, right);
succeeds = true;
}
}
return succeeds;
}
///
/// Creates a well balanced tree from a collection of values.
///
/// Values collection.
/// Well balanced tree, or null if values is null.
public static Node Create(ICollection values)
{
Node result = null;
if (values != null)
{
using (IEnumerator enumerator = values.GetEnumerator())
{
result = Create(enumerator, values.Count);
}
}
return result;
}
///
/// Creates a well balanced tree from a collection of values.
///
/// Values collection.
/// Well balanced tree, or null if values is null.
public static Node Create(IEnumerator values, int count)
{
Node result = null;
if ((values != null) && (count > 0))
{
int leftCount = count / 2;
int rightCount = count - leftCount - 1;
Node left = leftCount > 0 ? Create(values, leftCount) : null;
values.MoveNext();
V value = values.Current;
Node right = rightCount > 0 ? Create(values, rightCount) : null;
result = new Node(left, right, value);
}
return result;
}
///
/// Gets subtree height for the balanced subtree size.
///
/// Subtree size
/// Subtree height
public static int Height(int size)
{
int result = 0;
if (size != 0)
{
if ((size & 0xffff0000) == 0)
{
result -= 16;
size <<= 16;
}
if ((size & 0xff000000) == 0)
{
result -= 8;
size <<= 8;
}
if ((size & 0xf0000000) == 0)
{
result -= 4;
size <<= 4;
}
if ((size & 0xc0000000) == 0)
{
result -= 2;
size <<= 2;
}
result += (int)((uint)size >> 31) + 31;
}
return result;
}
///
/// Reserves path for the depth.
///
/// A required length.
///
/// A new path.
///
private Node[] ReserveDepth(int length)
{
if (length < 8)
{
length = 8;
}
else if (length < 16)
{
length = 16;
}
else if (length < 24)
{
length = 24;
}
else if (length < 32)
{
length = 32;
}
// No more cases.
var newPath = new Node[length];
var path = this.path;
for(int i = 0; i < path.Length; ++i)
{
if (i >= depth)
{
break;
}
newPath[i] = path[i];
}
this.path = newPath;
return newPath;
}
///
/// Replaces the current node.
///
/// A new node.
private void Replace(Node newNode)
{
Node node = current;
var path = this.path;
path[depth - 1] = newNode;
current = newNode;
for(int i = depth - 1; i-- > 0;)
{
Node parent = path[i];
Node left = parent.Left;
Node right;
if (left == node)
{
left = newNode;
right = parent.Right;
}
else
{
right = newNode;
}
node = parent;
newNode = new Node(left, right, parent);
path[i] = newNode;
}
}
///
/// Removes node with two children and balances the tree.
///
private void RemoveAndBalance()
{
int i = depth - 1;
Node node = current;
Node parent;
Node newParent;
Node left;
Node right;
Node newNode;
if (node.Left.Size >= node.Right.Size)
{
MoveToPredecessor();
MoveToParent();
parent = current;
if (i == depth - 1)
{
newParent = parent.Left;
left = parent.Left.Left;
right = parent.Right;
}
else
{
node = parent;
newParent = parent.Right;
left = parent.Left;
right = parent.Right.Left;
}
}
else
{
MoveToSuccessor();
MoveToParent();
parent = current;
if (i == depth - 1)
{
newParent = parent.Right;
left = parent.Left;
right = parent.Right.Right;
}
else
{
node = parent;
newParent = parent.Left;
left = parent.Left.Right;
right = parent.Right;
}
}
int j = depth - 1;
var path = this.path;
while(j > i)
{
newNode = new Node(left, right, node);
path[j] = null;
parent = path[--j];
left = parent.Left;
if (left == node)
{
left = newNode;
right = parent.Right;
}
else
{
right = newNode;
}
node = parent;
}
depth = i + 1;
newNode = new Node(left, right, newParent);
Replace(newNode);
Balance(newNode.Left, newNode.Right);
}
/// Balances the tree.
/// A left child.
/// A right child.
private void Balance(Node left, Node right)
{
Node node = current;
int i = depth;
var path = this.path;
while(true)
{
path[--i] = null;
Node newNode;
Node leftLeft;
Node leftRight;
Node rightRight;
Node rightLeft;
int l;
int r;
int ll;
int lr;
int rr;
int rl;
if (left != null)
{
l = left.Size;
leftLeft = left.Left;
leftRight = left.Right;
ll = leftLeft != null ? leftLeft.Size : 0;
lr = leftRight != null ? leftRight.Size : 0;
}
else
{
leftLeft = null;
leftRight = null;
l = 0;
ll = 0;
lr = 0;
}
if (right != null)
{
rightRight = right.Right;
rightLeft = right.Left;
r = right.Size;
rr = rightRight != null ? rightRight.Size : 0;
rl = rightLeft != null ? rightLeft.Size : 0;
}
else
{
rightRight = null;
rightLeft = null;
r = 0;
rr = 0;
rl = 0;
}
if ((ll > r) && (ll > lr))
{
// LL
newNode = new Node(
leftLeft,
new Node(leftRight, right, node),
left);
}
else if ((lr > r) ||
((ll == r) && (leftRight != null) && (leftRight.Left != null)))
{
// LR
newNode = new Node(
new Node(leftLeft, leftRight.Left, left),
new Node(leftRight.Right, right, node),
leftRight);
}
else if ((rr > l) && (rr > rl))
{
// RR
newNode = new Node(
new Node(left, rightLeft, node),
rightRight,
right);
}
else if ((rl > l) ||
((rr == l) && (rightLeft != null) && (rightLeft.Right != null)))
{
// RL
newNode = new Node(
new Node(left, rightLeft.Left, node),
new Node(rightLeft.Right, rightRight, right),
rightLeft);
}
else
{
newNode = (node.Left == left) && (node.Right == right) ?
node : new Node(left, right, node);
}
if (i == 0)
{
current = newNode;
path[0] = newNode;
depth = 1;
break;
}
Node next = path[i - 1];
left = next.Left;
if (left == node)
{
left = newNode;
right = next.Right;
}
else
{
right = newNode;
}
node = next;
}
}
///
/// A current node.
///
private Node current;
///
/// A node path.
///
private Node[] path = empty;
///
/// A depth of path.
///
private int depth;
///
/// Empty path.
///
private static readonly Node[] empty = {};
}
///
/// An API to work with tree.
///
public static class API
{
///
/// Gets a tree navigator for a node.
///
/// A node to get a tree navigator for.
/// A tree navigator.
public static TreeNavigator Navigator(
this TreeNavigator.Node node)
{
return new TreeNavigator(node);
}
///
/// Navigates to a node within a tree, which is equal or closest to
/// a specified key.
///
/// A tree navigator.
/// A key of a find.
///
/// 0 when current node is equal to,
/// -1 when found node is less than, and
/// 1 when found node is greater than the searched one.
///
/// If tree is empty then 1 is returned.
///
/// A key type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the key.
///
public static int Find(this TreeNavigator navigator, K key)
{
return Find(navigator, key, Comparer.Default);
}
///
/// Navigates to a node within a tree, which is equal or closest to
/// a specified key. Comparer is used to test equality.
///
/// A tree navigator.
/// A key of a find.
/// A key comparer.
///
/// 0 when current node is equal to,
/// -1 when found node is less than, and
/// 1 when found node is greater than the searched one.
///
/// If tree is empty then 1 is returned.
///
/// A key type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the comparer.
///
public static int Find(
this TreeNavigator navigator,
K key,
IComparer comparer)
{
int c;
if (!navigator.MoveToRoot())
{
c = -1;
}
else
{
while(true)
{
c = comparer.Compare(navigator.Current.Value, key);
if ((c == 0) ||
(c < 0 ? !navigator.MoveToRight() : !navigator.MoveToLeft()))
{
break;
}
}
}
return c;
}
///
/// Navigates to a node within a tree, which is equal or closest to
/// a specified value.
///
/// A tree navigator.
/// A key value of a find.
///
/// 0 when current node is equal to,
/// -1 when found node is less than, and
/// 1 when found node is greater than the searched one.
///
/// If tree is empty then 1 is returned.
///
/// A key type.
/// A value type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the key.
///
public static int Find(
this TreeNavigator> navigator,
K key)
{
return Find(navigator, key, Comparer.Default);
}
///
/// Navigates to a node within a tree, which is equal or closest to
/// a specified value. Comparer is used to test equality.
///
/// A tree navigator.
/// A key value of a find.
/// A key comparer.
///
/// 0 when current node is equal to,
/// -1 when found node is less than, and
/// 1 when found node is greater than the searched one.
///
/// If tree is empty then 1 is returned.
///
/// A key type.
/// A value type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the comparer.
///
public static int Find(
this TreeNavigator> navigator,
K key,
IComparer comparer)
{
int c;
if (!navigator.MoveToRoot())
{
c = -1;
}
else
{
while(true)
{
c = comparer.Compare(navigator.Current.Value.Key, key);
if ((c == 0) ||
(c < 0 ? !navigator.MoveToRight() : !navigator.MoveToLeft()))
{
break;
}
}
}
return c;
}
///
/// Navigates to a node within a tree, which is equal to a specified value.
/// Comparer is used to test equality.
///
/// A node.
/// A key of a find.
/// Found node or null if node is not found.
/// A key type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the key.
///
public static TreeNavigator.Node Find(
this TreeNavigator.Node node,
K key)
{
return Find(node, key, Comparer.Default);
}
///
/// Navigates to a node within a tree, which is equal to a specified value.
/// Comparer is used to test equality.
///
/// A node.
/// A key of a find.
/// A key comparer.
/// Found node or null if node is not found.
/// A key type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the comparer.
///
public static TreeNavigator.Node Find(
this TreeNavigator.Node node,
K key,
IComparer comparer)
{
while(node != null)
{
int c = comparer.Compare(node.Value, key);
if (c == 0)
{
break;
}
node = c < 0 ? node.Right : node.Left;
}
return node;
}
///
/// Navigates to a node within a tree, which is equal to a specified value.
/// Comparer is used to test equality.
///
/// A node.
/// A key value of a find.
/// Found node or null if node is not found.
/// A key type.
/// A value type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the key.
///
public static TreeNavigator>.Node Find(
this TreeNavigator>.Node node,
K key)
{
return Find(node, key, Comparer.Default);
}
///
/// Navigates to a node within a tree, which is equal to a specified value.
/// Comparer is used to test equality.
///
/// A node.
/// A key value of a find.
/// A key comparer.
/// Found node or null if node is not found.
/// A key type.
/// A value type.
///
/// Method works properly wheNode nodes in the tree are ordered
/// according to the comparer.
///
public static TreeNavigator>.Node Find(
this TreeNavigator>.Node node,
K key,
IComparer comparer)
{
while(node != null)
{
int c = comparer.Compare(node.Value.Key, key);
if (c == 0)
{
break;
}
node = c < 0 ? node.Right : node.Left;
}
return node;
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A key to insert.
/// A key comparer.
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
public static int Insert(
this TreeNavigator navigator,
K key,
IComparer comparer)
{
return Insert(navigator, key, comparer, false);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A key to insert.
/// A key comparer.
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
public static int Insert(this TreeNavigator navigator, K key)
{
return Insert(navigator, key, Comparer.Default, false);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A key to insert.
///
/// true to insert duplicate, and false otherwise.
///
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
public static int Insert(
this TreeNavigator navigator,
K key,
bool insertDuplicate)
{
return Insert(navigator, key, Comparer.Default, insertDuplicate);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A key to insert.
/// A key comparer.
///
/// true to insert duplicate, and false otherwise.
///
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
public static int Insert(
this TreeNavigator navigator,
K key,
IComparer comparer,
bool insertDuplicate)
{
int c = Find(navigator, key, comparer);
int index = navigator.Index;
if ((c == 0) && !insertDuplicate)
{
index = -index;
}
else
{
if (c <= 0)
{
++index;
}
navigator.Insert(key, c > 0);
}
return index;
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A value to insert.
/// A key comparer.
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
/// A value type.
public static int Insert(
this TreeNavigator> navigator,
KeyValuePair value,
IComparer comparer)
{
return Insert(navigator, value, comparer, false);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A value to insert.
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
/// A value type.
public static int Insert(
this TreeNavigator> navigator,
KeyValuePair value)
{
return Insert(navigator, value, Comparer.Default, false);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A value to insert.
///
/// true to insert duplicate, and false otherwise.
///
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
/// A value type.
public static int Insert(
this TreeNavigator> navigator,
KeyValuePair value,
bool insertDuplicate)
{
return Insert(navigator, value, Comparer.Default, insertDuplicate);
}
///
/// Inserts a node with a specified key into the tree.
///
/// A tree navigator.
/// A value to insert.
/// A key comparer.
///
/// true to insert duplicate, and false otherwise.
///
///
/// Index of inserted node, or negative index of node
/// if no node is not inserted due to duplicate.
///
/// A key type.
/// A value type.
public static int Insert(
this TreeNavigator> navigator,
KeyValuePair value,
IComparer comparer,
bool insertDuplicate)
{
int c = Find(navigator, value.Key, comparer);
int index = navigator.Index;
if ((c == 0) && !insertDuplicate)
{
index = -index;
}
else
{
if (c <= 0)
{
++index;
}
navigator.Insert(value, c > 0);
}
return index;
}
///
/// Removes a node with a specified key.
///
/// A tree navigator.
/// A key to remove.
///
/// Index of removed nore, or -1 if no node is removed.
///
/// A key type.
public static int Remove(this TreeNavigator navigator, K key)
{
return Remove(navigator, key, Comparer.Default);
}
///
/// Removes a node with a specified key.
///
/// A tree navigator.
/// A key to remove.
/// A key comparer.
///
/// Index of removed nore, or -1 if no node is removed.
///
/// A key type.
public static int Remove(
this TreeNavigator navigator,
K key,
IComparer comparer)
{
int index;
int c = Find(navigator, key, comparer);
if (c != 0)
{
index = -1;
}
else
{
index = navigator.Index;
navigator.Remove();
}
return index;
}
///
/// Removes a node with a specified key.
///
/// A tree navigator.
/// A key to remove.
///
/// Index of removed nore, or -1 if no node is removed.
///
/// A key type.
/// A value type.
public static int Remove(
this TreeNavigator> navigator,
K key)
{
return Remove(navigator, key, Comparer.Default);
}
///
/// Removes a node with a specified key.
///
/// A tree navigator.
/// A key to remove.
/// A key comparer.
///
/// Index of removed nore, or -1 if no node is removed.
///
/// A key type.
public static int Remove(
this TreeNavigator> navigator,
K key,
IComparer comparer)
{
int index;
int c = Find(navigator, key, comparer);
if (c != 0)
{
index = -1;
}
else
{
index = navigator.Index;
navigator.Remove();
}
return index;
}
///
/// Enumerates values for a specified key.
///
/// A tree navigator.
/// A key to get values for.
/// An enumerator.
/// A key type.
/// A value type.
public static IEnumerable> GetValues(
this TreeNavigator> navigator,
K key)
{
return GetValues(navigator, key, Comparer.Default);
}
///
/// Enumerates values for a specified key.
///
/// A tree navigator.
/// A key to get values for.
/// A key comparer.
/// An enumerator.
/// A key type.
/// A value type.
public static IEnumerable> GetValues(
this TreeNavigator> navigator,
K key,
IComparer comparer)
{
navigator = navigator.Root.Navigator();
int c = Find(navigator, key, comparer);
if (c == 0)
{
while(navigator.MoveToPredecessor())
{
if (comparer.Compare(navigator.Current.Value.Key, key) != 0)
{
navigator.MoveToSuccessor();
break;
}
}
do
{
yield return navigator.Current.Value;
}
while(navigator.MoveToSuccessor() &&
(comparer.Compare(navigator.Current.Value.Key, key) != 0));
}
}
}
}