PageRenderTime 57ms CodeModel.GetById 27ms RepoModel.GetById 1ms app.codeStats 0ms

/System.Xronos/Language/Collections/TreeNode.cs

https://bitbucket.org/stefanrusek/xronos
C# | 460 lines | 377 code | 59 blank | 24 comment | 64 complexity | f23e6ffeb3d959680daed7dcc6279e56 MD5 | raw file
  1. /* ****************************************************************************
  2. *
  3. * Copyright (c) 2008 Stefan Rusek and Benjamin Pollack
  4. *
  5. * Permission is hereby granted, free of charge, to any person obtaining a copy
  6. * of this software and associated documentation files (the "Software"), to deal
  7. * in the Software without restriction, including without limitation the rights
  8. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  9. * copies of the Software, and to permit persons to whom the Software is
  10. * furnished to do so, subject to the following conditions:
  11. *
  12. * The above copyright notice and this permission notice shall be included in
  13. * all copies or substantial portions of the Software.
  14. *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  16. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  17. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  18. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  19. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  20. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  21. * THE SOFTWARE.
  22. *
  23. * ***************************************************************************/
  24. using System;
  25. using System.Collections.Generic;
  26. using System.Linq;
  27. using System.Text;
  28. using System.Runtime.InteropServices;
  29. namespace System.Xronos.Language.Collections
  30. {
  31. public class TreeNode<TKey, TValue> : MapEntryBase
  32. {
  33. public TKey Key { get; private set; }
  34. public TValue Value { get; private set; }
  35. TreeNode<TKey, TValue> Left { get; set; }
  36. TreeNode<TKey, TValue> Right { get; set; }
  37. int? _length;
  38. int Length
  39. {
  40. get
  41. {
  42. if (!_length.HasValue)
  43. _length = Math.Max(Left != null ? Left.Length : 0, Right != null ? Right.Length : 0) + 1;
  44. return _length.Value;
  45. }
  46. }
  47. int? _count;
  48. internal int Count
  49. {
  50. get
  51. {
  52. if (!_count.HasValue)
  53. _count = (Right != null ? Right.Count : 0) + (Left != null ? Left.Count : 0) + 1;
  54. return _count.Value;
  55. }
  56. }
  57. int? _bfactor;
  58. int BalancingFactor
  59. {
  60. get
  61. {
  62. if (!_bfactor.HasValue)
  63. _bfactor = (Right != null ? Right.Length : 0) - (Left != null ? Left.Length : 0);
  64. return _bfactor.Value;
  65. }
  66. }
  67. public override string ToString()
  68. {
  69. return string.Format("<{0}, {1}, {2}>", Key, Value, BalancingFactor);
  70. }
  71. struct History
  72. {
  73. public History(TreeNode<TKey, TValue> node, int direction) { Node = node; Direction = direction; }
  74. public TreeNode<TKey, TValue> Node;
  75. public int Direction;
  76. }
  77. private static bool Find(TreeNode<TKey, TValue> root, List<History> list, IComparer<TKey> compare, TKey key, out TreeNode<TKey, TValue> item, out int direction)
  78. {
  79. item = null;
  80. direction = 0;
  81. var node = root;
  82. while (node != null)
  83. {
  84. direction = -compare.Compare(node.Key, key);
  85. switch (direction)
  86. {
  87. case -1:
  88. if (list != null) list.Add(new History(node, -1));
  89. node = node.Left;
  90. break;
  91. case 1:
  92. if (list != null) list.Add(new History(node, 1));
  93. node = node.Right;
  94. break;
  95. case 0:
  96. item = node;
  97. return true;
  98. }
  99. }
  100. return false;
  101. }
  102. public ISequence All()
  103. {
  104. return seq(() => null);
  105. }
  106. private ISequence seq(Func<ISequence> next)
  107. {
  108. var rightNext = next;
  109. if (Right != null)
  110. rightNext = () => Right.seq(next);
  111. if (Left == null)
  112. return LazySequence.Create(this, rightNext);
  113. else
  114. return Left.seq(() => LazySequence.Create(this, rightNext));
  115. }
  116. public static bool Lookup(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key, out TValue value)
  117. {
  118. value = default(TValue);
  119. TreeNode<TKey, TValue> item;
  120. int direction;
  121. if (Find(root, null, compare, key, out item, out direction))
  122. {
  123. value = item.Value;
  124. return true;
  125. }
  126. return false;
  127. }
  128. public static TreeNode<TKey, TValue> Insert(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key, TValue value, bool overwrite)
  129. {
  130. if (root == null)
  131. return new TreeNode<TKey, TValue>
  132. {
  133. Key = key,
  134. Value = value
  135. };
  136. var list = new List<History>();
  137. var node = root;
  138. int direction = 0;
  139. if (Find(root, list, compare, key, out node, out direction))
  140. {
  141. if (!overwrite)
  142. throw new ArgumentException("Duplicate key", "key");
  143. return Replace(list, new TreeNode<TKey, TValue>
  144. {
  145. Key = node.Key,
  146. Value = value,
  147. Left = node.Left,
  148. Right = node.Right
  149. });
  150. }
  151. else
  152. return Insert(list, new TreeNode<TKey, TValue> { Key = key, Value = value });
  153. }
  154. public static TreeNode<TKey, TValue> Remove(TreeNode<TKey, TValue> root, IComparer<TKey> compare, TKey key)
  155. {
  156. var list = new List<History>();
  157. TreeNode<TKey, TValue> item;
  158. int direction;
  159. if (!Find(root, list, compare, key, out item, out direction))
  160. return root;
  161. // just insert null for leaf nodes
  162. if (item.BalancingFactor == 0 && item.Right == null)
  163. {
  164. item = null;
  165. }
  166. else
  167. {
  168. int ix = list.Count;
  169. list.Add(new TreeNode<TKey, TValue>.History(item, 0));
  170. TreeNode<TKey, TValue> replacement;
  171. if (item.BalancingFactor < 0)
  172. {
  173. replacement = FollowChildren(list, item.Left, n => n.Right, 1);
  174. item = replacement.Left;
  175. direction = -1;
  176. }
  177. else
  178. {
  179. replacement = FollowChildren(list, item.Right, n => n.Left, -1);
  180. item = replacement.Right;
  181. direction = 1;
  182. }
  183. list[ix] = new TreeNode<TKey, TValue>.History(new TreeNode<TKey, TValue>
  184. {
  185. Key = replacement.Key,
  186. Value = replacement.Value,
  187. Left = list[ix].Node.Left,
  188. Right = list[ix].Node.Right
  189. }, direction);
  190. }
  191. return Insert(list, item);
  192. }
  193. private static TreeNode<TKey, TValue> FollowChildren(List<History> list, TreeNode<TKey, TValue> item, Func<TreeNode<TKey, TValue>, TreeNode<TKey, TValue>> getNext, int direction)
  194. {
  195. var next = getNext(item);
  196. while (next != null)
  197. {
  198. list.Add(new History(item, direction));
  199. item = next;
  200. next = getNext(item);
  201. }
  202. return item;
  203. }
  204. private static TreeNode<TKey, TValue> Insert(List<History> list, TreeNode<TKey, TValue> child)
  205. {
  206. return Replace(list, child);
  207. }
  208. #region Promotion & Rebalancing
  209. private static TreeNode<TKey, TValue> RebalanceRoot(TreeNode<TKey, TValue> child)
  210. {
  211. History grand;
  212. if (child.BalancingFactor < -1)
  213. {
  214. grand = new History(child, -1);
  215. child = child.Left;
  216. }
  217. else if (child.BalancingFactor > 1)
  218. {
  219. grand = new History(child, 1);
  220. child = child.Right;
  221. }
  222. else
  223. return child;
  224. History parent;
  225. if (child.BalancingFactor < 0)
  226. {
  227. parent = new History(child, -1);
  228. child = child.Left;
  229. }
  230. else
  231. {
  232. parent = new History(child, 1);
  233. child = child.Right;
  234. }
  235. return Promote(grand, parent, child);
  236. }
  237. private static TreeNode<TKey, TValue> Promote(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
  238. {
  239. if (parent.Direction == grand.Direction)
  240. return PromoteParent(grand, parent, child);
  241. else
  242. return PromoteChild(grand, parent, child);
  243. }
  244. private static TreeNode<TKey, TValue> PromoteChild(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
  245. {
  246. var newParent = new TreeNode<TKey, TValue>
  247. {
  248. Key = parent.Node.Key,
  249. Value = parent.Node.Value,
  250. Left = parent.Direction < 0 ? child.Right : parent.Node.Left,
  251. Right = parent.Direction > 0 ? child.Left : parent.Node.Right,
  252. };
  253. var newGrand = new TreeNode<TKey, TValue>
  254. {
  255. Key = grand.Node.Key,
  256. Value = grand.Node.Value,
  257. Left = grand.Direction < 0 ? child.Right : grand.Node.Left,
  258. Right = grand.Direction > 0 ? child.Left : grand.Node.Right,
  259. };
  260. child.Left = parent.Direction < 0 ? newGrand : newParent;
  261. child.Right = parent.Direction > 0 ? newGrand : newParent;
  262. child._bfactor = null;
  263. child._length = null;
  264. return child;
  265. }
  266. private static TreeNode<TKey, TValue> PromoteParent(TreeNode<TKey, TValue>.History grand, TreeNode<TKey, TValue>.History parent, TreeNode<TKey, TValue> child)
  267. {
  268. var newGrand = new TreeNode<TKey, TValue>
  269. {
  270. Key = grand.Node.Key,
  271. Value = grand.Node.Value,
  272. Left = grand.Direction < 0 ? parent.Node.Right : grand.Node.Left,
  273. Right = grand.Direction > 0 ? parent.Node.Left : grand.Node.Right,
  274. };
  275. var newParent = new TreeNode<TKey, TValue>
  276. {
  277. Key = parent.Node.Key,
  278. Value = parent.Node.Value,
  279. Left = parent.Direction < 0 ? child : newGrand,
  280. Right = parent.Direction > 0 ? child : newGrand,
  281. };
  282. return newParent;
  283. }
  284. #endregion
  285. private static TreeNode<TKey, TValue> Replace(List<History> list, TreeNode<TKey, TValue> child)
  286. {
  287. for (int i = list.Count - 1; i >= 0; i--)
  288. {
  289. var left = child;
  290. var right = child;
  291. var parent = list[i];
  292. if (parent.Direction > 0)
  293. left = parent.Node.Left;
  294. else
  295. right = parent.Node.Right;
  296. child = new TreeNode<TKey, TValue>
  297. {
  298. Key = parent.Node.Key,
  299. Value = parent.Node.Value,
  300. Left = left,
  301. Right = right
  302. };
  303. child = RebalanceRoot(child);
  304. }
  305. return child;
  306. }
  307. public override object key()
  308. {
  309. return Key;
  310. }
  311. public override object val()
  312. {
  313. return Value;
  314. }
  315. }
  316. public class ReferenceComparator<T> : IComparer<T>
  317. {
  318. static IComparer<T> _default;
  319. public static IComparer<T> Default
  320. {
  321. get
  322. {
  323. return _default ?? (_default = new ReferenceComparator<T>());
  324. }
  325. }
  326. #region IComparer<object> Members
  327. public int Compare(T x, T y)
  328. {
  329. if (x == null && y == null)
  330. return 0;
  331. if (x == null)
  332. return -1;
  333. if (y == null)
  334. return 1;
  335. var tcx = Convert.GetTypeCode(x);
  336. var tcy = Convert.GetTypeCode(y);
  337. if (IsInteger(tcx) && IsInteger(tcy))
  338. return Comparer<long>.Default.Compare(Convert.ToInt64(x), Convert.ToInt64(y));
  339. if (IsUnsigned(tcx) && IsUnsigned(tcy))
  340. return Comparer<ulong>.Default.Compare(Convert.ToUInt64(x), Convert.ToUInt64(y));
  341. if (IsNumeric(tcx) && IsNumeric(tcy))
  342. return Comparer<double>.Default.Compare(Convert.ToDouble(x), Convert.ToDouble(y));
  343. int i = x.GetType().FullName.CompareTo(y.GetType().FullName);
  344. if (i != 0)
  345. return i;
  346. IComparable comp = x as IComparable;
  347. if (comp != null)
  348. return comp.CompareTo(y);
  349. comp = y as IComparable;
  350. if (comp != null)
  351. return -comp.CompareTo(x);
  352. throw new InvalidOperationException("one type must be IComparable");
  353. }
  354. private static bool IsInteger(TypeCode tcx)
  355. {
  356. switch (tcx)
  357. {
  358. case TypeCode.Int16:
  359. case TypeCode.Int32:
  360. case TypeCode.Int64:
  361. case TypeCode.SByte:
  362. return true;
  363. default:
  364. return false;
  365. }
  366. }
  367. private static bool IsUnsigned(TypeCode tcx)
  368. {
  369. switch (tcx)
  370. {
  371. case TypeCode.UInt16:
  372. case TypeCode.UInt32:
  373. case TypeCode.UInt64:
  374. case TypeCode.Byte:
  375. return true;
  376. default:
  377. return false;
  378. }
  379. }
  380. private static bool IsNumeric(TypeCode tcx)
  381. {
  382. switch (tcx)
  383. {
  384. case TypeCode.Int16:
  385. case TypeCode.Int32:
  386. case TypeCode.Int64:
  387. case TypeCode.SByte:
  388. case TypeCode.UInt16:
  389. case TypeCode.UInt32:
  390. case TypeCode.UInt64:
  391. case TypeCode.Byte:
  392. case TypeCode.Single:
  393. case TypeCode.Double:
  394. return true;
  395. default:
  396. return false;
  397. }
  398. }
  399. #endregion
  400. }
  401. }