SortedDictionary.cs 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788
  1. // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
  2. #if NO_SORTEDDICTIONARY
  3. using System;
  4. using System.Diagnostics;
  5. //
  6. // Code ported from SortedDictionary.cs and SortedSet.cs in the BCL.
  7. // Unused portions have been removed for brevity.
  8. //
  9. namespace System.Collections.Generic
  10. {
  11. class SortedDictionary<TKey, TValue> : IEnumerable<KeyValuePair<TKey, TValue>>
  12. {
  13. private readonly TreeSet<KeyValuePair<TKey, TValue>> _set;
  14. public SortedDictionary()
  15. {
  16. _set = new TreeSet<KeyValuePair<TKey, TValue>>(new KeyValuePairComparer());
  17. }
  18. public void Add(TKey key, TValue value)
  19. {
  20. _set.Add(new KeyValuePair<TKey, TValue>(key, value));
  21. }
  22. public int Count
  23. {
  24. get
  25. {
  26. return _set.Count;
  27. }
  28. }
  29. public bool Remove(TKey key)
  30. {
  31. return _set.Remove(new KeyValuePair<TKey, TValue>(key, default(TValue)));
  32. }
  33. public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
  34. {
  35. return new Enumerator(this);
  36. }
  37. IEnumerator IEnumerable.GetEnumerator()
  38. {
  39. return GetEnumerator();
  40. }
  41. public struct Enumerator : IEnumerator<KeyValuePair<TKey, TValue>>
  42. {
  43. private readonly TreeSet<KeyValuePair<TKey, TValue>>.Enumerator _treeEnum;
  44. internal Enumerator(SortedDictionary<TKey, TValue> dictionary)
  45. {
  46. _treeEnum = dictionary._set.GetEnumerator();
  47. }
  48. public bool MoveNext()
  49. {
  50. return _treeEnum.MoveNext();
  51. }
  52. public void Dispose()
  53. {
  54. _treeEnum.Dispose();
  55. }
  56. public KeyValuePair<TKey, TValue> Current
  57. {
  58. get
  59. {
  60. return _treeEnum.Current;
  61. }
  62. }
  63. object IEnumerator.Current
  64. {
  65. get
  66. {
  67. return new KeyValuePair<TKey, TValue>(Current.Key, Current.Value);
  68. }
  69. }
  70. internal void Reset()
  71. {
  72. _treeEnum.Reset();
  73. }
  74. void IEnumerator.Reset()
  75. {
  76. _treeEnum.Reset();
  77. }
  78. }
  79. internal class KeyValuePairComparer : Comparer<KeyValuePair<TKey, TValue>>
  80. {
  81. private readonly IComparer<TKey> _keyComparer = Comparer<TKey>.Default;
  82. public override int Compare(KeyValuePair<TKey, TValue> x, KeyValuePair<TKey, TValue> y)
  83. {
  84. return _keyComparer.Compare(x.Key, y.Key);
  85. }
  86. }
  87. internal class TreeSet<T> : SortedSet<T>
  88. {
  89. public TreeSet(IComparer<T> comparer)
  90. : base(comparer)
  91. {
  92. }
  93. internal override bool AddIfNotPresent(T item)
  94. {
  95. var ret = base.AddIfNotPresent(item);
  96. if (!ret)
  97. {
  98. throw new ArgumentException("Duplicate entry added.");
  99. }
  100. return ret;
  101. }
  102. }
  103. }
  104. class SortedSet<T> : IEnumerable<T>
  105. {
  106. private readonly IComparer<T> _comparer;
  107. private Node _root;
  108. private int _count;
  109. private int _version;
  110. public SortedSet(IComparer<T> comparer)
  111. {
  112. _comparer = comparer;
  113. }
  114. public int Count
  115. {
  116. get
  117. {
  118. return _count;
  119. }
  120. }
  121. public bool Add(T item)
  122. {
  123. return AddIfNotPresent(item);
  124. }
  125. internal virtual bool AddIfNotPresent(T item)
  126. {
  127. if (_root == null)
  128. {
  129. _root = new Node(item, false);
  130. _count = 1;
  131. _version++;
  132. return true;
  133. }
  134. //
  135. // Search for a node at bottom to insert the new node.
  136. // If we can guarantee the node we found is not a 4-node, it would be easy to do insertion.
  137. // We split 4-nodes along the search path.
  138. //
  139. Node current = _root;
  140. Node parent = null;
  141. Node grandParent = null;
  142. Node greatGrandParent = null;
  143. //
  144. // Even if we don't actually add to the set, we may be altering its structure (by doing rotations
  145. // and such). so update version to disable any enumerators/subsets working on it.
  146. //
  147. _version++;
  148. int order = 0;
  149. while (current != null)
  150. {
  151. order = _comparer.Compare(item, current.Item);
  152. if (order == 0)
  153. {
  154. // We could have changed root node to red during the search process.
  155. // We need to set it to black before we return.
  156. _root.IsRed = false;
  157. return false;
  158. }
  159. // split a 4-node into two 2-nodes
  160. if (Is4Node(current))
  161. {
  162. Split4Node(current);
  163. // We could have introduced two consecutive red nodes after split. Fix that by rotation.
  164. if (IsRed(parent))
  165. {
  166. InsertionBalance(current, ref parent, grandParent, greatGrandParent);
  167. }
  168. }
  169. greatGrandParent = grandParent;
  170. grandParent = parent;
  171. parent = current;
  172. current = (order < 0) ? current.Left : current.Right;
  173. }
  174. Debug.Assert(parent != null, "Parent node cannot be null here!");
  175. var node = new Node(item);
  176. if (order > 0)
  177. {
  178. parent.Right = node;
  179. }
  180. else
  181. {
  182. parent.Left = node;
  183. }
  184. //
  185. // The new node will be red, so we will need to adjust the colors if parent node is also red.
  186. //
  187. if (parent.IsRed)
  188. {
  189. InsertionBalance(node, ref parent, grandParent, greatGrandParent);
  190. }
  191. //
  192. // Root node is always black.
  193. //
  194. _root.IsRed = false;
  195. ++_count;
  196. return true;
  197. }
  198. public bool Remove(T item)
  199. {
  200. return DoRemove(item); // hack so it can be made non-virtual
  201. }
  202. internal virtual bool DoRemove(T item)
  203. {
  204. if (_root == null)
  205. {
  206. return false;
  207. }
  208. // Search for a node and then find its succesor.
  209. // Then copy the item from the succesor to the matching node and delete the successor.
  210. // If a node doesn't have a successor, we can replace it with its left child (if not empty.)
  211. // or delete the matching node.
  212. //
  213. // In top-down implementation, it is important to make sure the node to be deleted is not a 2-node.
  214. // Following code will make sure the node on the path is not a 2 Node.
  215. //
  216. // Even if we don't actually remove from the set, we may be altering its structure (by doing rotations
  217. // and such). so update version to disable any enumerators/subsets working on it.
  218. //
  219. _version++;
  220. Node current = _root;
  221. Node parent = null;
  222. Node grandParent = null;
  223. Node match = null;
  224. Node parentOfMatch = null;
  225. bool foundMatch = false;
  226. while (current != null)
  227. {
  228. if (Is2Node(current))
  229. { // fix up 2-Node
  230. if (parent == null)
  231. { // current is root. Mark it as red
  232. current.IsRed = true;
  233. }
  234. else
  235. {
  236. Node sibling = GetSibling(current, parent);
  237. if (sibling.IsRed)
  238. {
  239. // If parent is a 3-node, flip the orientation of the red link.
  240. // We can acheive this by a single rotation
  241. // This case is converted to one of other cased below.
  242. Debug.Assert(!parent.IsRed, "parent must be a black node!");
  243. if (parent.Right == sibling)
  244. {
  245. RotateLeft(parent);
  246. }
  247. else
  248. {
  249. RotateRight(parent);
  250. }
  251. parent.IsRed = true;
  252. sibling.IsRed = false; // parent's color
  253. // sibling becomes child of grandParent or root after rotation. Update link from grandParent or root
  254. ReplaceChildOfNodeOrRoot(grandParent, parent, sibling);
  255. // sibling will become grandParent of current node
  256. grandParent = sibling;
  257. if (parent == match)
  258. {
  259. parentOfMatch = sibling;
  260. }
  261. // update sibling, this is necessary for following processing
  262. sibling = (parent.Left == current) ? parent.Right : parent.Left;
  263. }
  264. Debug.Assert(sibling != null || sibling.IsRed == false, "sibling must not be null and it must be black!");
  265. if (Is2Node(sibling))
  266. {
  267. Merge2Nodes(parent, current, sibling);
  268. }
  269. else
  270. {
  271. // current is a 2-node and sibling is either a 3-node or a 4-node.
  272. // We can change the color of current to red by some rotation.
  273. TreeRotation rotation = RotationNeeded(parent, current, sibling);
  274. Node newGrandParent = null;
  275. switch (rotation)
  276. {
  277. case TreeRotation.RightRotation:
  278. Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
  279. Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!");
  280. sibling.Left.IsRed = false;
  281. newGrandParent = RotateRight(parent);
  282. break;
  283. case TreeRotation.LeftRotation:
  284. Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
  285. Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!");
  286. sibling.Right.IsRed = false;
  287. newGrandParent = RotateLeft(parent);
  288. break;
  289. case TreeRotation.RightLeftRotation:
  290. Debug.Assert(parent.Right == sibling, "sibling must be left child of parent!");
  291. Debug.Assert(sibling.Left.IsRed, "Left child of sibling must be red!");
  292. newGrandParent = RotateRightLeft(parent);
  293. break;
  294. case TreeRotation.LeftRightRotation:
  295. Debug.Assert(parent.Left == sibling, "sibling must be left child of parent!");
  296. Debug.Assert(sibling.Right.IsRed, "Right child of sibling must be red!");
  297. newGrandParent = RotateLeftRight(parent);
  298. break;
  299. }
  300. newGrandParent.IsRed = parent.IsRed;
  301. parent.IsRed = false;
  302. current.IsRed = true;
  303. ReplaceChildOfNodeOrRoot(grandParent, parent, newGrandParent);
  304. if (parent == match)
  305. {
  306. parentOfMatch = newGrandParent;
  307. }
  308. grandParent = newGrandParent;
  309. }
  310. }
  311. }
  312. // we don't need to compare any more once we found the match
  313. int order = foundMatch ? -1 : _comparer.Compare(item, current.Item);
  314. if (order == 0)
  315. {
  316. // save the matching node
  317. foundMatch = true;
  318. match = current;
  319. parentOfMatch = parent;
  320. }
  321. grandParent = parent;
  322. parent = current;
  323. if (order < 0)
  324. {
  325. current = current.Left;
  326. }
  327. else
  328. {
  329. current = current.Right; // continue the search in right sub tree after we find a match
  330. }
  331. }
  332. // move successor to the matching node position and replace links
  333. if (match != null)
  334. {
  335. ReplaceNode(match, parentOfMatch, parent, grandParent);
  336. --_count;
  337. }
  338. if (_root != null)
  339. {
  340. _root.IsRed = false;
  341. }
  342. return foundMatch;
  343. }
  344. public Enumerator GetEnumerator()
  345. {
  346. return new Enumerator(this);
  347. }
  348. IEnumerator<T> IEnumerable<T>.GetEnumerator()
  349. {
  350. return new Enumerator(this);
  351. }
  352. IEnumerator IEnumerable.GetEnumerator()
  353. {
  354. return new Enumerator(this);
  355. }
  356. private static Node GetSibling(Node node, Node parent)
  357. {
  358. if (parent.Left == node)
  359. {
  360. return parent.Right;
  361. }
  362. return parent.Left;
  363. }
  364. // After calling InsertionBalance, we need to make sure current and parent up-to-date.
  365. // It doesn't matter if we keep grandParent and greatGrantParent up-to-date
  366. // because we won't need to split again in the next node.
  367. // By the time we need to split again, everything will be correctly set.
  368. //
  369. private void InsertionBalance(Node current, ref Node parent, Node grandParent, Node greatGrandParent)
  370. {
  371. Debug.Assert(grandParent != null, "Grand parent cannot be null here!");
  372. bool parentIsOnRight = (grandParent.Right == parent);
  373. bool currentIsOnRight = (parent.Right == current);
  374. Node newChildOfGreatGrandParent;
  375. if (parentIsOnRight == currentIsOnRight)
  376. { // same orientation, single rotation
  377. newChildOfGreatGrandParent = currentIsOnRight ? RotateLeft(grandParent) : RotateRight(grandParent);
  378. }
  379. else
  380. { // different orientaton, double rotation
  381. newChildOfGreatGrandParent = currentIsOnRight ? RotateLeftRight(grandParent) : RotateRightLeft(grandParent);
  382. // current node now becomes the child of greatgrandparent
  383. parent = greatGrandParent;
  384. }
  385. // grand parent will become a child of either parent of current.
  386. grandParent.IsRed = true;
  387. newChildOfGreatGrandParent.IsRed = false;
  388. ReplaceChildOfNodeOrRoot(greatGrandParent, grandParent, newChildOfGreatGrandParent);
  389. }
  390. private static bool Is2Node(Node node)
  391. {
  392. Debug.Assert(node != null, "node cannot be null!");
  393. return IsBlack(node) && IsNullOrBlack(node.Left) && IsNullOrBlack(node.Right);
  394. }
  395. private static bool Is4Node(Node node)
  396. {
  397. return IsRed(node.Left) && IsRed(node.Right);
  398. }
  399. private static bool IsBlack(Node node)
  400. {
  401. return (node != null && !node.IsRed);
  402. }
  403. private static bool IsNullOrBlack(Node node)
  404. {
  405. return (node == null || !node.IsRed);
  406. }
  407. private static bool IsRed(Node node)
  408. {
  409. return (node != null && node.IsRed);
  410. }
  411. private static void Merge2Nodes(Node parent, Node child1, Node child2)
  412. {
  413. Debug.Assert(IsRed(parent), "parent must be be red");
  414. // combing two 2-nodes into a 4-node
  415. parent.IsRed = false;
  416. child1.IsRed = true;
  417. child2.IsRed = true;
  418. }
  419. // Replace the child of a parent node.
  420. // If the parent node is null, replace the root.
  421. private void ReplaceChildOfNodeOrRoot(Node parent, Node child, Node newChild)
  422. {
  423. if (parent != null)
  424. {
  425. if (parent.Left == child)
  426. {
  427. parent.Left = newChild;
  428. }
  429. else
  430. {
  431. parent.Right = newChild;
  432. }
  433. }
  434. else
  435. {
  436. _root = newChild;
  437. }
  438. }
  439. // Replace the matching node with its succesor.
  440. private void ReplaceNode(Node match, Node parentOfMatch, Node successor, Node parentOfSuccessor)
  441. {
  442. if (successor == match)
  443. { // this node has no successor, should only happen if right child of matching node is null.
  444. Debug.Assert(match.Right == null, "Right child must be null!");
  445. successor = match.Left;
  446. }
  447. else
  448. {
  449. Debug.Assert(parentOfSuccessor != null, "parent of successor cannot be null!");
  450. Debug.Assert(successor.Left == null, "Left child of succesor must be null!");
  451. Debug.Assert((successor.Right == null && successor.IsRed) || (successor.Right.IsRed && !successor.IsRed), "Succesor must be in valid state");
  452. if (successor.Right != null)
  453. {
  454. successor.Right.IsRed = false;
  455. }
  456. if (parentOfSuccessor != match)
  457. { // detach succesor from its parent and set its right child
  458. parentOfSuccessor.Left = successor.Right;
  459. successor.Right = match.Right;
  460. }
  461. successor.Left = match.Left;
  462. }
  463. if (successor != null)
  464. {
  465. successor.IsRed = match.IsRed;
  466. }
  467. ReplaceChildOfNodeOrRoot(parentOfMatch, match, successor);
  468. }
  469. internal void UpdateVersion()
  470. {
  471. ++_version;
  472. }
  473. private static Node RotateLeft(Node node)
  474. {
  475. var x = node.Right;
  476. node.Right = x.Left;
  477. x.Left = node;
  478. return x;
  479. }
  480. private static Node RotateLeftRight(Node node)
  481. {
  482. var child = node.Left;
  483. var grandChild = child.Right;
  484. node.Left = grandChild.Right;
  485. grandChild.Right = node;
  486. child.Right = grandChild.Left;
  487. grandChild.Left = child;
  488. return grandChild;
  489. }
  490. private static Node RotateRight(Node node)
  491. {
  492. var x = node.Left;
  493. node.Left = x.Right;
  494. x.Right = node;
  495. return x;
  496. }
  497. private static Node RotateRightLeft(Node node)
  498. {
  499. var child = node.Right;
  500. var grandChild = child.Left;
  501. node.Right = grandChild.Left;
  502. grandChild.Left = node;
  503. child.Left = grandChild.Right;
  504. grandChild.Right = child;
  505. return grandChild;
  506. }
  507. private static TreeRotation RotationNeeded(Node parent, Node current, Node sibling)
  508. {
  509. Debug.Assert(IsRed(sibling.Left) || IsRed(sibling.Right), "sibling must have at least one red child");
  510. if (IsRed(sibling.Left))
  511. {
  512. if (parent.Left == current)
  513. {
  514. return TreeRotation.RightLeftRotation;
  515. }
  516. return TreeRotation.RightRotation;
  517. }
  518. else
  519. {
  520. if (parent.Left == current)
  521. {
  522. return TreeRotation.LeftRotation;
  523. }
  524. return TreeRotation.LeftRightRotation;
  525. }
  526. }
  527. private static void Split4Node(Node node)
  528. {
  529. node.IsRed = true;
  530. node.Left.IsRed = false;
  531. node.Right.IsRed = false;
  532. }
  533. internal class Node
  534. {
  535. public bool IsRed;
  536. public T Item;
  537. public Node Left;
  538. public Node Right;
  539. public Node(T item)
  540. {
  541. // The default color will be red, we never need to create a black node directly.
  542. Item = item;
  543. IsRed = true;
  544. }
  545. public Node(T item, bool isRed)
  546. {
  547. // The default color will be red, we never need to create a black node directly.
  548. Item = item;
  549. IsRed = isRed;
  550. }
  551. }
  552. public struct Enumerator : IEnumerator<T>
  553. {
  554. private readonly SortedSet<T> _tree;
  555. private int _version;
  556. private readonly Stack<Node> _stack;
  557. private Node _current;
  558. internal Enumerator(SortedSet<T> set)
  559. {
  560. _tree = set;
  561. _version = _tree._version;
  562. // 2lg(n + 1) is the maximum height
  563. _stack = new Stack<Node>(2 * (int)SortedSet<T>.log2(set.Count + 1));
  564. _current = null;
  565. Intialize();
  566. }
  567. private void Intialize()
  568. {
  569. _current = null;
  570. Node node = _tree._root;
  571. Node next = null, other = null;
  572. while (node != null)
  573. {
  574. next = node.Left;
  575. other = node.Right;
  576. _stack.Push(node);
  577. node = next;
  578. }
  579. }
  580. public bool MoveNext()
  581. {
  582. if (_version != _tree._version)
  583. {
  584. throw new InvalidOperationException("Collection has changed during enumeration.");
  585. }
  586. if (_stack.Count == 0)
  587. {
  588. _current = null;
  589. return false;
  590. }
  591. _current = _stack.Pop();
  592. Node node = _current.Right;
  593. Node next = null, other = null;
  594. while (node != null)
  595. {
  596. next = node.Left;
  597. other = node.Right;
  598. _stack.Push(node);
  599. node = next;
  600. }
  601. return true;
  602. }
  603. public void Dispose()
  604. {
  605. }
  606. public T Current
  607. {
  608. get
  609. {
  610. if (_current != null)
  611. {
  612. return _current.Item;
  613. }
  614. return default(T);
  615. }
  616. }
  617. object IEnumerator.Current
  618. {
  619. get
  620. {
  621. if (_current == null)
  622. {
  623. throw new InvalidOperationException("Collection has changed during enumeration.");
  624. }
  625. return _current.Item;
  626. }
  627. }
  628. internal bool NotStartedOrEnded
  629. {
  630. get
  631. {
  632. return _current == null;
  633. }
  634. }
  635. internal void Reset()
  636. {
  637. if (_version != _tree._version)
  638. {
  639. throw new InvalidOperationException("Collection has changed during enumeration.");
  640. }
  641. _stack.Clear();
  642. Intialize();
  643. }
  644. void IEnumerator.Reset()
  645. {
  646. Reset();
  647. }
  648. }
  649. private static int log2(int value)
  650. {
  651. int c = 0;
  652. while (value > 0)
  653. {
  654. c++;
  655. value >>= 1;
  656. }
  657. return c;
  658. }
  659. }
  660. internal enum TreeRotation
  661. {
  662. LeftRotation = 1,
  663. RightRotation = 2,
  664. RightLeftRotation = 3,
  665. LeftRightRotation = 4,
  666. }
  667. }
  668. #endif