using System;
using System.Collections;
namespace CornedBee.Utility
{
///
/// This class is a tree node for the tree.
///
internal class TreeNode
{
///
/// The parent node.
///
internal TreeNode parent = null;
///
/// The left child node.
///
internal TreeNode left = null;
///
/// The right child node.
///
internal TreeNode right = null;
///
/// The height of this node's subtree.
///
internal int height;
///
/// The data. For dictionary trees, this is a KeyValuePair.
///
internal object data;
internal IComparable DataComp
{
get
{
return (IComparable)data;
}
}
internal TreeNode(object d)
{
data = d;
}
}
///
/// This class is a balanced binary tree.
///
internal class BinaryTree : System.Collections.ICollection
{
///
/// Test Main for this class.
///
/// Command line arguments.
private class TreeEnumerator : IEnumerator
{
private BinaryTree tree;
private TreeNode node;
public TreeEnumerator(BinaryTree t)
{
tree = t;
Reset();
}
#region IEnumerator Members
public void Reset()
{
node = null;
}
public object Current
{
get
{
return node.data;
}
}
public bool MoveNext()
{
if(node == null)
{
if(tree.root == null)
{
return false;
}
else
{
node = tree.Minimum(tree.root);
return true;
}
}
else
{
node = tree.Next(node);
return node != null;
}
}
#endregion
}
private TreeNode root = null;
private int count = 0;
public BinaryTree()
{
}
///
/// Gets the minimum node in n's subtree.
///
/// The local root node.
/// The node with the smallest value.
internal TreeNode Minimum(TreeNode n)
{
while(n.left != null)
{
n = n.left;
}
return n;
}
///
/// Gets the maximum node in n's subtree.
///
/// The local root node.
/// The node with the largest value.
internal TreeNode Maximum(TreeNode n)
{
while(n.right != null)
{
n = n.right;
}
return n;
}
///
/// Returns the next node in in-order traversal.
///
/// The current node.
/// The node with the next largest value.
internal TreeNode Next(TreeNode n)
{
if(n.right != null)
{
return Minimum(n.right);
}
else
{
TreeNode t = n.parent;
while(t != null && n == t.right)
{
n = t;
t = t.parent;
}
return t;
}
}
///
/// Returns the previous node in in-order traversal.
///
/// The current node.
/// The node with the next smallest value.
internal TreeNode Previous(TreeNode n)
{
if(n.left != null)
{
return Maximum(n.left);
}
else
{
TreeNode t = n.parent;
while(t != null && n == t.left)
{
n = t;
t = t.parent;
}
return t;
}
}
///
/// Recalculates the height of a node.
///
/// The node for which to recalculate the height.
private void AdjustHeight(TreeNode node)
{
int lw = node.left == null ? -1 : node.left.height;
int rw = node.right == null ? -1 : node.right.height;
node.height = Math.Max(lw, rw) + 1;
}
///
/// Helper method for rebalancing. Does a right rotation.
///
/// On entry the unbalanced node. On exit the node in its place.
private void RotateRight(ref TreeNode node)
{
TreeNode t = node.left;
node.left = t.right;
if(node.left != null)
node.left.parent = node;
t.right = node;
if(t.right != null)
t.right.parent = t;
t.parent = node.parent;
AdjustHeight(node);
AdjustHeight(t);
node = t;
}
///
/// Helper method for rebalancing. Does a left-right rotation.
///
/// On entry the unbalanced node. On exit the node in its place.
private void RotateLeftRight(ref TreeNode node)
{
RotateLeft(ref node.left);
RotateRight(ref node);
}
///
/// Helper method for rebalancing. Does a left rotation.
///
/// On entry the unbalanced node. On exit the node in its place.
private void RotateLeft(ref TreeNode node)
{
TreeNode t = node.right;
node.right = t.left;
if(node.right != null)
node.right.parent = node;
t.left = node;
t.parent = node.parent;
if(t.left != null)
t.left.parent = t;
AdjustHeight(node);
AdjustHeight(t);
node = t;
}
///
/// Helper method for rebalancing. Does a right-left rotation.
///
/// On entry the unbalanced node. On exit the node in its place.
private void RotateRightLeft(ref TreeNode node)
{
RotateRight(ref node.right);
RotateLeft(ref node);
}
///
/// Recursive insertion of a node, including rebalancing.
///
/// The new node.
/// The insertion location.
/// Whether the new node was passed to the left or the right. -1 is left, +1 right. 0 means this
/// node has the same key as the new one.
private int InternalAdd(TreeNode newN, ref TreeNode curN)
{
int comp = newN.DataComp.CompareTo(curN.data);
if(comp < 0)
{
if(curN.left == null)
{
curN.left = newN;
newN.parent = curN;
++count;
}
else
{
int subcomp = InternalAdd(newN, ref curN.left);
if(curN.right == null || curN.left.height - curN.right.height == 2)
{
if(subcomp < 0)
{
RotateRight(ref curN);
}
else
{
RotateLeftRight(ref curN);
}
}
}
}
else if(comp > 0)
{
if(curN.right == null)
{
curN.right = newN;
newN.parent = curN;
++count;
}
else
{
int subcomp = InternalAdd(newN, ref curN.right);
if(curN.left == null || curN.right.height - curN.left.height == 2)
{
if(subcomp > 0)
{
RotateLeft(ref curN);
}
else
{
RotateRightLeft(ref curN);
}
}
}
}
else
{
return 0;
}
AdjustHeight(curN);
return comp;
}
///
/// Finds the node that contains value.
///
/// The value of the node to be found.
/// The node, or null.
private TreeNode FindNode(object value)
{
TreeNode n = root;
while(n != null)
{
int comp = n.DataComp.CompareTo(value);
if(comp == 0)
{
break;
}
else if(comp < 0)
{
n = n.right;
}
else
{
n = n.left;
}
}
return n;
}
///
/// Finds the balance of a node. The balance is the difference between
/// the left and the right subheights.
///
/// The node.
/// The balance. Positive means the right tree is heavier.
private int Balance(TreeNode n)
{
int lh = n.left != null ? n.left.height : -1;
int rh = n.right != null ? n.right.height : -1;
return rh - lh;
}
///
/// Re-establishes the tree balance after a deletion.
///
/// The current node to rebalance.
private void Rebalance(ref TreeNode n)
{
int bal = Balance(n);
if(bal <= -2)
{
// Unbalanced to the left.
int subbal = Balance(n.left);
if(subbal < 0)
{
// Subtree leans left
RotateRight(ref n);
}
else
{
// Subtree leans right
RotateLeftRight(ref n);
}
}
else if(bal >= 2)
{
// Unbalanced to the right.
int subbal = Balance(n.right);
if(subbal < 0)
{
// Subtree leans left
RotateRightLeft(ref n);
}
else
{
// Subtree leans right
RotateLeft(ref n);
}
}
// Balance parent.
if(n.parent != null)
Rebalance(ref n.parent);
else
root = n;
}
#region ICollection Members
public bool IsSynchronized
{
get
{
return false;
}
}
public int Count
{
get
{
return count;
}
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public object SyncRoot
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return new TreeEnumerator(this);
}
#endregion
internal object Get(object value)
{
TreeNode n = FindNode(value);
if(n != null)
return n.data;
return null;
}
public void Remove(object value)
{
TreeNode n = FindNode(value);
if(n != null)
{
--count;
TreeNode r;
if(n.left == null || n.right == null)
{
r = n;
}
else
{
r = Next(n);
n.data = r.data;
}
n = (r.left == null) ? r.right : r.left;
if(n != null)
n.parent = r.parent;
if(r.parent == null)
{
root = n;
}
else
{
if(r == r.parent.left)
r.parent.left = n;
else
r.parent.right = n;
}
// Node unlinked, GC will collect it.
// Now rebalance the tree.
// r.parent might be null, but then the tree contained only one or two elements.
// Which means it doesn't need rebalancing anyway.
if(r.parent != null)
{
Rebalance(ref r.parent);
}
}
}
public bool Contains(object value)
{
return FindNode(value) != null;
}
public void Clear()
{
// This should suffice.
root = null;
}
public void Add(object value)
{
TreeNode n = new TreeNode(value);
if(root == null)
{
root = n;
++count;
}
else
{
InternalAdd(n, ref root);
}
}
}
///
/// A set is a collection that is optimized for fast "Contains" calls.
///
public interface ISet : ICollection
{
///
/// Adds an object to the set.
///
/// The value to add.
public void Add(object value);
///
/// Removes an object from the set. Does nothing if
/// the value isn't in the set.
///
/// The value to remove.
public void Remove(object value);
///
/// Tests if an object is in the set.
///
/// The value to look for.
/// True if the object is in the set.
public bool Contains(object value);
///
/// Completly clears the set.
///
public void Clear();
}
///
/// An implementation of ISet based on a binary tree.
/// Contains performance is O(log n).
///
public class TreeSet : ISet
{
BinaryTree impl = new BinaryTree();
IComparer comp;
internal class DataWrapper : IComparable
{
internal IComparer comparer;
internal object data;
public DataWrapper(object value, IComparer comp)
{
data = value;
comparer = comp;
if(comparer == null)
comparer = Comparer.Default;
}
#region IComparable Members
public int CompareTo(object obj)
{
if(!(obj is DataWrapper))
throw new ArgumentException("Not a DataWrapper", "obj");
DataWrapper wrap = (DataWrapper)obj;
return comparer.Compare(data, wrap.data);
}
#endregion
}
internal class EnumWrapper : IEnumerator
{
private IEnumerator inner;
public EnumWrapper(IEnumerator e)
{
inner = e;
}
#region IEnumerator Members
public void Reset()
{
inner.Reset();
}
public object Current
{
get
{
DataWrapper wrap = (DataWrapper)inner.Current;
return wrap.data;
}
}
public bool MoveNext()
{
return inner.MoveNext();
}
#endregion
}
///
/// Creates a new TreeSet.
///
public TreeSet()
{
comp = null;
}
///
/// Creates a new TreeSet using a custom comparer.
///
/// The comparer to use for sorting.
public TreeSet(IComparer c)
{
comp = c;
}
#region ISet Members
public void Add(object value)
{
impl.Add(new DataWrapper(value, comp));
}
public void Remove(object value)
{
impl.Remove(new DataWrapper(value, comp));
}
public bool Contains(object value)
{
return impl.Contains(new DataWrapper(value, comp));
}
public void Clear()
{
impl.Clear();
}
#endregion
#region ICollection Members
public bool IsSynchronized
{
get
{
return false;
}
}
public int Count
{
get
{
return impl.Count;
}
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public object SyncRoot
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region IEnumerable Members
public IEnumerator GetEnumerator()
{
return new EnumWrapper(impl.GetEnumerator());
}
#endregion
}
///
/// Binary-Tree-based dictionary.
///
public class TreeDictionary : IDictionary
{
BinaryTree impl = new BinaryTree();
IComparer comp;
public TreeDictionary()
{
comp = Comparer.Default;
}
public TreeDictionary(IComparer c)
{
comp = c;
}
public class KeyValuePair : DictionaryEntry, IComparable
{
internal object key;
internal object value;
internal IComparer comp;
public KeyValuePair(object k, object v)
{
comp = Comparer.Default;
key = k;
value = v;
}
public KeyValuePair(object k, object v, IComparer comp)
{
this.comp = comp;
key = k;
value = v;
}
public object Key
{
get
{
return key;
}
set
{
throw new NotSupportedException("Keys cannot be modified.");
}
}
public object Value
{
get
{
return value;
}
set
{
this.value = value;
}
}
#region IComparable Members
public int CompareTo(object obj)
{
if(!(obj is KeyValuePair))
throw new ArgumentException("not a KeyValuePair", "obj");
KeyValuePair kvp = (KeyValuePair)obj;
return comp.Compare(key, kvp.key);
}
#endregion
}
internal class DictEnum : IDictionaryEnumerator
{
internal IEnumerator inner;
public DictEnum(IEnumerator e)
{
inner = e;
}
#region IDictionaryEnumerator Members
internal KeyValuePair Get()
{
return (KeyValuePair)inner.Current;
}
public object Key
{
get
{
return Get().Key;
}
}
public object Value
{
get
{
return Get().Value;
}
}
public DictionaryEntry Entry
{
get
{
return Get();
}
}
#endregion
#region IEnumerator Members
public void Reset()
{
inner.Reset();
}
public object Current
{
get
{
return Entry;
}
}
public bool MoveNext()
{
return inner.MoveNext();
}
#endregion
}
#region IDictionary Members
public bool IsReadOnly
{
get
{
return false;
}
}
public IDictionaryEnumerator GetEnumerator()
{
return new DictEnum(impl.GetEnumerator());
}
public object this[object key]
{
get
{
object o = impl.Get(new KeyValuePair(key, null, comp));
if(o == null)
return null;
return ((KeyValuePair)o).Value;
}
set
{
object o = impl.Get(new KeyValuePair(key, null, comp));
if(o == null)
{
impl.Add(new KeyValuePair(key, value, comp));
}
else
{
((KeyValuePair)o).Value = value;
}
}
}
public void Remove(object key)
{
impl.Remove(new KeyValuePair(key, null, comp));
}
public bool Contains(object key)
{
return impl.Contains(new KeyValuePair(key, null, comp));
}
public void Clear()
{
impl.Clear();
}
public ICollection Values
{
get
{
throw new NotImplementedException();
}
}
public void Add(object key, object value)
{
impl.Add(new KeyValuePair(key, value, comp));
}
public ICollection Keys
{
get
{
throw new NotImplementedException();
}
}
public bool IsFixedSize
{
get
{
return false;
}
}
#endregion
#region ICollection Members
public bool IsSynchronized
{
get
{
return false;
}
}
public int Count
{
get
{
return impl.Count;
}
}
public void CopyTo(Array array, int index)
{
throw new NotImplementedException();
}
public object SyncRoot
{
get
{
throw new NotImplementedException();
}
}
#endregion
#region IEnumerable Members
IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return new DictEnum(impl.GetEnumerator());
}
#endregion
}
}