/Raven.Database/Storage/Managed/Munin/Tree/AVLTree.cs

http://github.com/ayende/ravendb · C# · 456 lines · 390 code · 50 blank · 16 comment · 56 complexity · d8bc1b8ab083790cc23d2ce95cf9b5ba MD5 · raw file

  1. //-----------------------------------------------------------------------
  2. // <copyright file="AVLTree.cs" company="Hibernating Rhinos LTD">
  3. // Copyright (c) Hibernating Rhinos LTD. All rights reserved.
  4. // </copyright>
  5. //-----------------------------------------------------------------------
  6. using System;
  7. using System.Collections.Generic;
  8. using System.Linq;
  9. using Raven.Json.Linq;
  10. namespace Raven.Munin.Tree
  11. {
  12. // Code originated from
  13. // http://blogs.msdn.com/b/ericlippert/archive/2008/01/21/immutability-in-c-part-nine-academic-plus-my-avl-tree-implementation.aspx
  14. public sealed class AVLTree<TKey, TValue> : IBinarySearchTree<TKey, TValue>
  15. {
  16. private readonly int height;
  17. public override string ToString()
  18. {
  19. return string.Format("Key: {0}, Value: {1}, Count: {2}", theKey, theValue, Count);
  20. }
  21. public RavenJObject ToJObject()
  22. {
  23. return new RavenJObject
  24. {
  25. {"key", RavenJToken.FromObject(theKey)},
  26. {"value", RavenJToken.FromObject(theValue)},
  27. {"left", Left.ToJObject()},
  28. {"right", Right.ToJObject()}
  29. };
  30. }
  31. private readonly IComparer<TKey> comparer;
  32. private readonly Func<TKey, TKey> deepCopyKey;
  33. private readonly Func<TValue, TValue> deepCopyValue;
  34. private readonly TKey theKey;
  35. private readonly IBinarySearchTree<TKey, TValue> left;
  36. private readonly IBinarySearchTree<TKey, TValue> right;
  37. private readonly TValue theValue;
  38. public int Count { get; private set; }
  39. internal AVLTree(
  40. IComparer<TKey> comparer,
  41. Func<TKey, TKey> deepCopyKey,
  42. Func<TValue, TValue> deepCopyValue,
  43. TKey key,
  44. TValue value,
  45. IBinarySearchTree<TKey, TValue> left,
  46. IBinarySearchTree<TKey, TValue> right)
  47. {
  48. this.comparer = comparer;
  49. this.deepCopyKey = deepCopyKey;
  50. this.deepCopyValue = deepCopyValue;
  51. this.theKey = key;
  52. this.theValue = value;
  53. this.left = left;
  54. this.right = right;
  55. height = 1 + Math.Max(Height(left), Height(right));
  56. Count = 1 + Left.Count + Right.Count;
  57. }
  58. // IBinaryTree
  59. #region IBinarySearchTree<TKey,TValue> Members
  60. public IComparer<TKey> Comparer
  61. {
  62. get { return comparer; }
  63. }
  64. public bool IsEmpty
  65. {
  66. get { return false; }
  67. }
  68. public TValue Value
  69. {
  70. get { return deepCopyValue(theValue); }
  71. }
  72. public IBinarySearchTree<TKey, TValue> LeftMost
  73. {
  74. get
  75. {
  76. if(Left.IsEmpty)
  77. return this;
  78. var current = Left;
  79. while (current.Left.IsEmpty == false)
  80. current = current.Left;
  81. return current.LeftMost;
  82. }
  83. }
  84. public IBinarySearchTree<TKey, TValue> RightMost
  85. {
  86. get
  87. {
  88. if (Right.IsEmpty)
  89. return this;
  90. var current = Right;
  91. while (current.Right.IsEmpty == false)
  92. current = current.Right;
  93. return current.RightMost;
  94. }
  95. }
  96. // IBinarySearchTree
  97. public IBinarySearchTree<TKey, TValue> Left
  98. {
  99. get { return left; }
  100. }
  101. public IBinarySearchTree<TKey, TValue> Right
  102. {
  103. get { return right; }
  104. }
  105. public IBinarySearchTree<TKey, TValue> LocateNearest(TKey key, Predicate<TValue> isMatch)
  106. {
  107. if (isMatch(Value))
  108. return this;
  109. int compare = comparer.Compare(key, theKey);
  110. if (compare == 0)
  111. return this;
  112. if (compare > 0)
  113. return Right.LocateNearest(key, isMatch);
  114. return Left.LocateNearest(key, isMatch);
  115. }
  116. public IBinarySearchTree<TKey, TValue> Search(TKey key)
  117. {
  118. int compare = comparer.Compare(key, theKey);
  119. if (compare == 0)
  120. return this;
  121. if (compare > 0)
  122. return Right.Search(key);
  123. return Left.Search(key);
  124. }
  125. public IEnumerable<TValue> GreaterThan(TKey gtKey)
  126. {
  127. int compare = comparer.Compare(theKey, gtKey);
  128. if (compare <= 0)
  129. {
  130. foreach (var value in Right.GreaterThan(gtKey))
  131. {
  132. yield return value;
  133. }
  134. yield break;
  135. }
  136. foreach (var value in Left.GreaterThan(gtKey))
  137. {
  138. yield return value;
  139. }
  140. yield return Value;
  141. foreach (var value in Right.GreaterThan(gtKey))
  142. {
  143. yield return value;
  144. }
  145. }
  146. public IEnumerable<TValue> LessThan(TKey ltKey)
  147. {
  148. int compare = comparer.Compare(theKey, ltKey);
  149. if(compare < 0)
  150. {
  151. foreach (var value in Right.LessThan(ltKey))
  152. {
  153. yield return value;
  154. }
  155. }
  156. if (compare <= 0)
  157. yield return Value;
  158. foreach (var value in Left.LessThan(ltKey))
  159. {
  160. yield return value;
  161. }
  162. }
  163. public IEnumerable<TValue> LessThanOrEqual(TKey ltKey)
  164. {
  165. int compare = comparer.Compare(theKey, ltKey);
  166. if (compare < 0)
  167. {
  168. foreach (var value in Right.LessThanOrEqual(ltKey))
  169. {
  170. yield return value;
  171. }
  172. }
  173. if (compare <= 0)
  174. {
  175. yield return Value;
  176. }
  177. foreach (var value in Left.LessThanOrEqual(ltKey))
  178. {
  179. yield return value;
  180. }
  181. }
  182. public IEnumerable<TValue> GreaterThanOrEqual(TKey gteKey)
  183. {
  184. int compare = comparer.Compare(theKey, gteKey);
  185. if (compare < 0)
  186. {
  187. foreach (var value in Right.GreaterThanOrEqual(gteKey))
  188. {
  189. yield return value;
  190. }
  191. yield break;
  192. }
  193. foreach (var value in Left.GreaterThanOrEqual(gteKey))
  194. {
  195. yield return value;
  196. }
  197. yield return Value;
  198. foreach (var value in Right.GreaterThanOrEqual(gteKey))
  199. {
  200. yield return value;
  201. }
  202. }
  203. public TKey Key
  204. {
  205. get { return deepCopyKey(theKey); }
  206. }
  207. public IBinarySearchTree<TKey, TValue> Add(TKey key, TValue value)
  208. {
  209. AVLTree<TKey, TValue> result;
  210. var compare = comparer.Compare(key, theKey);
  211. if(compare == 0)
  212. return new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, key, value, Left, Right);
  213. if (compare > 0)
  214. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left, Right.Add(key, value));
  215. else
  216. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left.Add(key, value), Right);
  217. return MakeBalanced(result);
  218. }
  219. public IBinarySearchTree<TKey, TValue> AddOrUpdate(TKey key, TValue value, Func<TKey, TValue, TValue> updateValueFactory)
  220. {
  221. AVLTree<TKey, TValue> result;
  222. var compare = comparer.Compare(key, theKey);
  223. if (compare > 0)
  224. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left, Right.AddOrUpdate(key, value, updateValueFactory));
  225. else if(compare < 0)
  226. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left.AddOrUpdate(key, value, updateValueFactory), Right);
  227. else
  228. {
  229. var newValue = updateValueFactory(key, theValue);
  230. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, key, newValue, Left, Right);
  231. }
  232. return MakeBalanced(result);
  233. }
  234. public IBinarySearchTree<TKey, TValue> TryRemove(TKey key, out bool removed, out TValue value)
  235. {
  236. IBinarySearchTree<TKey, TValue> result;
  237. int compare = comparer.Compare(key, theKey);
  238. if (compare == 0)
  239. {
  240. removed = true;
  241. value = theValue;
  242. // We have a match. If this is a leaf, just remove it
  243. // by returning Empty. If we have only one child,
  244. // replace the node with the child.
  245. if (Right.IsEmpty && Left.IsEmpty)
  246. result = new EmptyAVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue);
  247. else if (Right.IsEmpty && !Left.IsEmpty)
  248. result = Left;
  249. else if (!Right.IsEmpty && Left.IsEmpty)
  250. result = Right;
  251. else
  252. {
  253. // We have two children. Remove the next-highest node and replace
  254. // this node with it.
  255. IBinarySearchTree<TKey, TValue> successor = Right;
  256. while (!successor.Left.IsEmpty)
  257. successor = successor.Left;
  258. bool ignoredBool;
  259. TValue ignoredValue;
  260. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, successor.Key, successor.Value, Left, Right.TryRemove(successor.Key, out ignoredBool, out ignoredValue));
  261. }
  262. }
  263. else if (compare < 0)
  264. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left.TryRemove(key, out removed, out value), Right);
  265. else
  266. result = new AVLTree<TKey, TValue>(comparer, deepCopyKey, deepCopyValue, theKey, theValue, Left, Right.TryRemove(key, out removed, out value));
  267. return MakeBalanced(result);
  268. }
  269. // IMap
  270. public bool Contains(TKey key)
  271. {
  272. return !Search(key).IsEmpty;
  273. }
  274. public bool TryGetValue(TKey key, out TValue value)
  275. {
  276. value = default(TValue);
  277. IBinarySearchTree<TKey, TValue> tree = Search(key);
  278. if (tree.IsEmpty)
  279. return false;
  280. value = tree.Value;
  281. return true;
  282. }
  283. public IEnumerable<TKey> KeysInOrder
  284. {
  285. get { return from t in EnumerateInOrder() select t.Key; }
  286. }
  287. public IEnumerable<TKey> KeysInReverseOrder
  288. {
  289. get { return from t in EnumerateInReverseOrder() select t.Key; }
  290. }
  291. public IEnumerable<TValue> ValuesInOrder
  292. {
  293. get { return from t in EnumerateInOrder() select t.Value; }
  294. }
  295. public IEnumerable<TValue> ValuesInReverseOrder
  296. {
  297. get { return from t in EnumerateInReverseOrder() select t.Value; }
  298. }
  299. public IEnumerable<KeyValuePair<TKey, TValue>> Pairs
  300. {
  301. get { return from t in EnumerateInOrder() select new KeyValuePair<TKey, TValue>(t.Key, t.Value); }
  302. }
  303. #endregion
  304. private IEnumerable<IBinarySearchTree<TKey, TValue>> EnumerateInOrder()
  305. {
  306. var stack = Stack<IBinarySearchTree<TKey, TValue>>.Empty;
  307. for (IBinarySearchTree<TKey, TValue> current = this; !current.IsEmpty || !stack.IsEmpty; current = current.Right)
  308. {
  309. while (!current.IsEmpty)
  310. {
  311. stack = stack.Push(current);
  312. current = current.Left;
  313. }
  314. current = stack.Peek();
  315. stack = stack.Pop();
  316. yield return current;
  317. }
  318. }
  319. private IEnumerable<IBinarySearchTree<TKey, TValue>> EnumerateInReverseOrder()
  320. {
  321. var stack = Stack<IBinarySearchTree<TKey, TValue>>.Empty;
  322. for (IBinarySearchTree<TKey, TValue> current = this; !current.IsEmpty || !stack.IsEmpty; current = current.Left)
  323. {
  324. while (!current.IsEmpty)
  325. {
  326. stack = stack.Push(current);
  327. current = current.Right;
  328. }
  329. current = stack.Peek();
  330. stack = stack.Pop();
  331. yield return current;
  332. }
  333. }
  334. // Static helpers for tree balancing
  335. private static int Height(IBinarySearchTree<TKey, TValue> tree)
  336. {
  337. if (tree.IsEmpty)
  338. return 0;
  339. return ((AVLTree<TKey, TValue>)tree).height;
  340. }
  341. private IBinarySearchTree<TKey, TValue> RotateLeft(IBinarySearchTree<TKey, TValue> tree)
  342. {
  343. if (tree.Right.IsEmpty)
  344. return tree;
  345. return new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Right.Key, tree.Right.Value,
  346. new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Key, tree.Value, tree.Left, tree.Right.Left),
  347. tree.Right.Right);
  348. }
  349. private IBinarySearchTree<TKey, TValue> RotateRight(IBinarySearchTree<TKey, TValue> tree)
  350. {
  351. if (tree.Left.IsEmpty)
  352. return tree;
  353. return new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Left.Key, tree.Left.Value, tree.Left.Left,
  354. new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Key, tree.Value, tree.Left.Right, tree.Right));
  355. }
  356. private IBinarySearchTree<TKey, TValue> DoubleLeft(IBinarySearchTree<TKey, TValue> tree)
  357. {
  358. if (tree.Right.IsEmpty)
  359. return tree;
  360. var rotatedRightChild = new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Key, tree.Value, tree.Left, RotateRight(tree.Right));
  361. return RotateLeft(rotatedRightChild);
  362. }
  363. private IBinarySearchTree<TKey, TValue> DoubleRight(IBinarySearchTree<TKey, TValue> tree)
  364. {
  365. if (tree.Left.IsEmpty)
  366. return tree;
  367. var rotatedLeftChild = new AVLTree<TKey, TValue>(tree.Comparer, deepCopyKey, deepCopyValue, tree.Key, tree.Value, RotateLeft(tree.Left), tree.Right);
  368. return RotateRight(rotatedLeftChild);
  369. }
  370. private static int Balance(IBinarySearchTree<TKey, TValue> tree)
  371. {
  372. if (tree.IsEmpty)
  373. return 0;
  374. return Height(tree.Right) - Height(tree.Left);
  375. }
  376. private static bool IsRightHeavy(IBinarySearchTree<TKey, TValue> tree)
  377. {
  378. return Balance(tree) >= 2;
  379. }
  380. private static bool IsLeftHeavy(IBinarySearchTree<TKey, TValue> tree)
  381. {
  382. return Balance(tree) <= -2;
  383. }
  384. private IBinarySearchTree<TKey, TValue> MakeBalanced(IBinarySearchTree<TKey, TValue> tree)
  385. {
  386. IBinarySearchTree<TKey, TValue> result;
  387. if (IsRightHeavy(tree))
  388. {
  389. if (IsLeftHeavy(tree.Right))
  390. result = DoubleLeft(tree);
  391. else
  392. result = RotateLeft(tree);
  393. }
  394. else if (IsLeftHeavy(tree))
  395. {
  396. if (IsRightHeavy(tree.Left))
  397. result = DoubleRight(tree);
  398. else
  399. result = RotateRight(tree);
  400. }
  401. else
  402. result = tree;
  403. return result;
  404. }
  405. }
  406. }