/System.Xronos/Language/Collections/TreeNode.cs
C# | 460 lines | 377 code | 59 blank | 24 comment | 64 complexity | f23e6ffeb3d959680daed7dcc6279e56 MD5 | raw file
- /* ****************************************************************************
- *
- * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy
- * of this software and associated documentation files (the "Software"), to deal
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- *
- * ***************************************************************************/
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- using System.Runtime.InteropServices;
-
- namespace System.Xronos.Language.Collections
- {
- public class TreeNode<TKey, TValue> : MapEntryBase
- {
- public TKey Key { get; private set; }
- public TValue Value { get; private set; }
-
- TreeNode<TKey, TValue> Left { get; set; }
- TreeNode<TKey, TValue> Right { get; set; }
-
- int? _length;
- int Length
- {
- get
- {
- if (!_length.HasValue)
- _length = Math.Max(Left != null ? Left.Length : 0, Right != null ? Right.Length : 0) + 1;
- return _length.Value;
- }
- }
-
- int? _count;
- internal int Count
- {
- get
- {
- if (!_count.HasValue)
- _count = (Right != null ? Right.Count : 0) + (Left != null ? Left.Count : 0) + 1;
- return _count.Value;
- }
- }
-
- int? _bfactor;
- int BalancingFactor
- {
- get
- {
- if (!_bfactor.HasValue)
- _bfactor = (Right != null ? Right.Length : 0) - (Left != null ? Left.Length : 0);
- return _bfactor.Value;
- }
- }
-
- public override string ToString()
- {
- return string.Format("<{0}, {1}, {2}>", Key, Value, BalancingFactor);
- }
-
- struct History
- {
- public History(TreeNode<TKey, TValue> node, int direction) { Node = node; Direction = direction; }
- public TreeNode<TKey, TValue> Node;
- public int Direction;
- }
-
- private static bool Find(TreeNode<TKey, TValue> root, List<History> list, IComparer<TKey> compare, TKey key, out TreeNode<TKey, TValue> item, out int direction)
- {
- item = null;
- direction = 0;
-
- var node = root;
- while (node != null)
- {
- direction = -compare.Compare(node.Key, key);
- switch (direction)
- {
- case -1:
- if (list != null) list.Add(new History(node, -1));
- node = node.Left;
- break;
- case 1:
- if (list != null) list.Add(new History(node, 1));
- node = node.Right;
- break;
- case 0:
- item = node;
- return true;
- }
- }
-
- return false;
- }
-
- public ISequence All()
- {
- return seq(() => null);
- }
-
- private ISequence seq(Func<ISequence> next)
- {
- var rightNext = next;
- if (Right != null)
- rightNext = () => Right.seq(next);
-
- if (Left == null)
- return LazySequence.Create(this, rightNext);
- else
- return Left.seq(() => LazySequence.Create(this, rightNext));
- }
-
- public static bool Lookup(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key, out TValue value)
- {
- value = default(TValue);
- TreeNode<TKey, TValue> item;
- int direction;
- if (Find(root, null, compare, key, out item, out direction))
- {
- value = item.Value;
- return true;
- }
- return false;
- }
-
- public static TreeNode<TKey, TValue> Insert(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key, TValue value, bool overwrite)
- {
- if (root == null)
- return new TreeNode<TKey, TValue>
- {
- Key = key,
- Value = value
- };
-
- var list = new List<History>();
-
- var node = root;
- int direction = 0;
-
- if (Find(root, list, compare, key, out node, out direction))
- {
- if (!overwrite)
- throw new ArgumentException("Duplicate key", "key");
- return Replace(list, new TreeNode<TKey, TValue>
- {
- Key = node.Key,
- Value = value,
- Left = node.Left,
- Right = node.Right
- });
- }
- else
- return Insert(list, new TreeNode<TKey, TValue> { Key = key, Value = value });
- }
-
- public static TreeNode<TKey, TValue> Remove(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key)
- {
- var list = new List<History>();
- TreeNode<TKey, TValue> item;
- int direction;
-
- if (!Find(root, list, compare, key, out item, out direction))
- return root;
-
- // just insert null for leaf nodes
- if (item.BalancingFactor == 0 && item.Right == null)
- {
- item = null;
- }
- else
- {
- int ix = list.Count;
- list.Add(new TreeNode<TKey, TValue>.History(item, 0));
-
- TreeNode<TKey, TValue> replacement;
-
- if (item.BalancingFactor < 0)
- {
- replacement = FollowChildren(list, item.Left, n => n.Right, 1);
- item = replacement.Left;
- direction = -1;
- }
- else
- {
- replacement = FollowChildren(list, item.Right, n => n.Left, -1);
- item = replacement.Right;
- direction = 1;
- }
-
- list[ix] = new TreeNode<TKey, TValue>.History(new TreeNode<TKey, TValue>
- {
- Key = replacement.Key,
- Value = replacement.Value,
- Left = list[ix].Node.Left,
- Right = list[ix].Node.Right
- }, direction);
- }
- return Insert(list, item);
- }
-
- private static TreeNode<TKey, TValue> FollowChildren(List<History> list, TreeNode<TKey, TValue> item, Func<TreeNode<TKey, TValue>, TreeNode<TKey, TValue>> getNext, int direction)
- {
- var next = getNext(item);
- while (next != null)
- {
- list.Add(new History(item, direction));
- item = next;
- next = getNext(item);
- }
- return item;
- }
-
- private static TreeNode<TKey, TValue> Insert(List<History> list, TreeNode<TKey, TValue> child)
- {
- return Replace(list, child);
- }
-
- #region Promotion & Rebalancing
- private static TreeNode<TKey, TValue> RebalanceRoot(TreeNode<TKey, TValue> child)
- {
- History grand;
- if (child.BalancingFactor < -1)
- {
- grand = new History(child, -1);
- child = child.Left;
- }
- else if (child.BalancingFactor > 1)
- {
- grand = new History(child, 1);
- child = child.Right;
- }
- else
- return child;
-
- History parent;
- if (child.BalancingFactor < 0)
- {
- parent = new History(child, -1);
- child = child.Left;
- }
- else
- {
- parent = new History(child, 1);
- child = child.Right;
- }
-
- return Promote(grand, parent, child);
- }
-
- private static TreeNode<TKey, TValue> Promote(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
- {
- if (parent.Direction == grand.Direction)
- return PromoteParent(grand, parent, child);
- else
- return PromoteChild(grand, parent, child);
- }
-
- private static TreeNode<TKey, TValue> PromoteChild(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
- {
- var newParent = new TreeNode<TKey, TValue>
- {
- Key = parent.Node.Key,
- Value = parent.Node.Value,
- Left = parent.Direction < 0 ? child.Right : parent.Node.Left,
- Right = parent.Direction > 0 ? child.Left : parent.Node.Right,
- };
-
- var newGrand = new TreeNode<TKey, TValue>
- {
- Key = grand.Node.Key,
- Value = grand.Node.Value,
- Left = grand.Direction < 0 ? child.Right : grand.Node.Left,
- Right = grand.Direction > 0 ? child.Left : grand.Node.Right,
- };
-
- child.Left = parent.Direction < 0 ? newGrand : newParent;
- child.Right = parent.Direction > 0 ? newGrand : newParent;
- child._bfactor = null;
- child._length = null;
-
- return child;
- }
-
- private static TreeNode<TKey, TValue> PromoteParent(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
- {
- var newGrand = new TreeNode<TKey, TValue>
- {
- Key = grand.Node.Key,
- Value = grand.Node.Value,
- Left = grand.Direction < 0 ? parent.Node.Right : grand.Node.Left,
- Right = grand.Direction > 0 ? parent.Node.Left : grand.Node.Right,
- };
-
- var newParent = new TreeNode<TKey, TValue>
- {
- Key = parent.Node.Key,
- Value = parent.Node.Value,
- Left = parent.Direction < 0 ? child : newGrand,
- Right = parent.Direction > 0 ? child : newGrand,
- };
-
- return newParent;
- }
- #endregion
-
- private static TreeNode<TKey, TValue> Replace(List<History> list, TreeNode<TKey, TValue> child)
- {
- for (int i = list.Count - 1; i >= 0; i--)
- {
- var left = child;
- var right = child;
-
- var parent = list[i];
-
- if (parent.Direction > 0)
- left = parent.Node.Left;
- else
- right = parent.Node.Right;
-
- child = new TreeNode<TKey, TValue>
- {
- Key = parent.Node.Key,
- Value = parent.Node.Value,
- Left = left,
- Right = right
- };
-
- child = RebalanceRoot(child);
- }
-
- return child;
- }
-
- public override object key()
- {
- return Key;
- }
-
- public override object val()
- {
- return Value;
- }
- }
-
- public class ReferenceComparator<T> : IComparer<T>
- {
- static IComparer<T> _default;
- public static IComparer<T> Default
- {
- get
- {
- return _default ?? (_default = new ReferenceComparator<T>());
- }
- }
-
- #region IComparer<object> Members
-
- public int Compare(T x, T y)
- {
- if (x == null && y == null)
- return 0;
- if (x == null)
- return -1;
- if (y == null)
- return 1;
-
- var tcx = Convert.GetTypeCode(x);
- var tcy = Convert.GetTypeCode(y);
-
- if (IsInteger(tcx) && IsInteger(tcy))
- return Comparer<long>.Default.Compare(Convert.ToInt64(x), Convert.ToInt64(y));
-
- if (IsUnsigned(tcx) && IsUnsigned(tcy))
- return Comparer<ulong>.Default.Compare(Convert.ToUInt64(x), Convert.ToUInt64(y));
-
- if (IsNumeric(tcx) && IsNumeric(tcy))
- return Comparer<double>.Default.Compare(Convert.ToDouble(x), Convert.ToDouble(y));
-
- int i = x.GetType().FullName.CompareTo(y.GetType().FullName);
- if (i != 0)
- return i;
-
- IComparable comp = x as IComparable;
- if (comp != null)
- return comp.CompareTo(y);
- comp = y as IComparable;
- if (comp != null)
- return -comp.CompareTo(x);
-
- throw new InvalidOperationException("one type must be IComparable");
- }
-
- private static bool IsInteger(TypeCode tcx)
- {
- switch (tcx)
- {
- case TypeCode.Int16:
- case TypeCode.Int32:
- case TypeCode.Int64:
- case TypeCode.SByte:
- return true;
- default:
- return false;
- }
- }
-
- private static bool IsUnsigned(TypeCode tcx)
- {
- switch (tcx)
- {
- case TypeCode.UInt16:
- case TypeCode.UInt32:
- case TypeCode.UInt64:
- case TypeCode.Byte:
- return true;
- default:
- return false;
- }
- }
-
- private static bool IsNumeric(TypeCode tcx)
- {
- switch (tcx)
- {
- case TypeCode.Int16:
- case TypeCode.Int32:
- case TypeCode.Int64:
- case TypeCode.SByte:
- case TypeCode.UInt16:
- case TypeCode.UInt32:
- case TypeCode.UInt64:
- case TypeCode.Byte:
- case TypeCode.Single:
- case TypeCode.Double:
- return true;
- default:
- return false;
- }
- }
-
- #endregion
- }
- }