AVLTree.cs 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941
  1. using System;
  2. using System.Collections.Generic;
  3. namespace Best.HTTP.Shared.Databases.Indexing
  4. {
  5. public enum Side
  6. {
  7. Left,
  8. Right
  9. }
  10. /// <summary>
  11. /// Implements most common list functions. With best case (no or only one item) it doesn't do any allocation.
  12. /// </summary>
  13. public struct NoAllocList<T>
  14. {
  15. private T _value;
  16. private bool _hasValue;
  17. private List<T> _values;
  18. public NoAllocList(T value)
  19. {
  20. this._value = value;
  21. this._hasValue = true;
  22. this._values = null;
  23. }
  24. public T this[int index] {
  25. get => this._hasValue ? this._value : this._values[index];
  26. set
  27. {
  28. if (index < 0 || (this._values == null && index > 0))
  29. throw new IndexOutOfRangeException(index.ToString());
  30. if (this._values != null)
  31. this._values[index] = value;
  32. else
  33. {
  34. this._value = value;
  35. this._hasValue = true;
  36. }
  37. }
  38. }
  39. public int Count { get => this._values != null ? this._values.Count : (this._hasValue ? 1 : 0); }
  40. public void Add(T item)
  41. {
  42. if (this._values != null)
  43. this._values.Add(item);
  44. else if (this._hasValue)
  45. {
  46. this._values = new List<T> { this._value, item };
  47. this._value = default(T);
  48. this._hasValue = false;
  49. }
  50. else
  51. {
  52. this._value = item;
  53. this._hasValue = true;
  54. }
  55. }
  56. public void Clear()
  57. {
  58. this._values?.Clear();
  59. this._values = null;
  60. this._value = default(T);
  61. this._hasValue = false;
  62. }
  63. public bool Contains(T item)
  64. {
  65. if (this._values != null)
  66. return this._values.Contains(item);
  67. // This can thrown a NullRefException if _value is null!
  68. return this._hasValue ? this._value.Equals(item) : false;
  69. }
  70. public bool Remove(T item)
  71. {
  72. if (this._values != null)
  73. return this._values.Remove(item);
  74. else if (this._hasValue && this._value.Equals(item))
  75. {
  76. this._value = default(T);
  77. this._hasValue = false;
  78. return true;
  79. }
  80. return false;
  81. }
  82. public void RemoveAt(int index)
  83. {
  84. if (index < 0 || (this._values == null && index > 0))
  85. throw new IndexOutOfRangeException(index.ToString());
  86. if (this._values != null)
  87. this._values.RemoveAt(index);
  88. else
  89. {
  90. this._value = default(T);
  91. this._hasValue = false;
  92. }
  93. }
  94. }
  95. public sealed class Node<KeyT, ValueT>
  96. {
  97. public Node<KeyT, ValueT> Parent, Left, Right;
  98. public KeyT Key { get; private set; }
  99. /// <summary>
  100. /// Depth of the node.
  101. /// </summary>
  102. public int Depth;
  103. /// <summary>
  104. /// Difference between LeftDepth and RightDepth.
  105. /// </summary>
  106. public int BalanceFactor { get { return this.LeftDepth - this.RightDepth; } }
  107. /// <summary>
  108. /// Left node's Depth, or -1 if it's null.
  109. /// </summary>
  110. public int LeftDepth { get { return this.Left == null ? -1 : this.Left.Depth; } }
  111. /// <summary>
  112. /// Right node's Depth, or -1 if it's null.
  113. /// </summary>
  114. public int RightDepth { get { return this.Right == null ? -1 : this.Right.Depth; } }
  115. public bool IsRoot { get { return this.Parent == null; } }
  116. public int ChildCount { get { return (this.Left == null ? 0 : 1) + (this.Right == null ? 0 : 1); } }
  117. // Stored values aren't public as modifing them requires special care.
  118. private NoAllocList<ValueT> _item;
  119. public Node(Node<KeyT, ValueT> parent, KeyT key, ValueT value)
  120. {
  121. this.Parent = parent;
  122. this.Key = key;
  123. this._item = new NoAllocList<ValueT>(value);
  124. // Depth is 0 by default, as it has no child
  125. this.Depth = 0;
  126. }
  127. public void BubbleUpDepthChange()
  128. {
  129. var current = this;
  130. while (current != null)
  131. {
  132. var oldDepth = current.Depth;
  133. current.Depth = Math.Max(current.LeftDepth, current.RightDepth) + 1;
  134. if (oldDepth != current.Depth)
  135. current = current.Parent;
  136. else
  137. break;
  138. }
  139. }
  140. public ValueT this[int index] { get => this._item[index]; }
  141. public int Count { get => this._item.Count; }
  142. public void Clear() => this._item = new NoAllocList<ValueT>();
  143. public void Add(ValueT value)
  144. {
  145. var tmp = this._item;
  146. tmp.Add(value);
  147. this._item = tmp;
  148. }
  149. public bool Remove(ValueT value)
  150. {
  151. var tmp = this._item;
  152. var result = tmp.Remove(value);
  153. if (result)
  154. this._item = tmp;
  155. return result;
  156. }
  157. public List<ValueT> ToList()
  158. {
  159. var list = new List<ValueT>(this._item.Count);
  160. for (int i = 0; i < this._item.Count; ++i)
  161. list.Add(this._item[i]);
  162. return list;
  163. }
  164. public override string ToString()
  165. {
  166. return $"{this.Left?.Key.ToString()} <- {this.Key.ToString()} -> {this.Right?.Key.ToString()}";
  167. }
  168. }
  169. // https://www.codesdope.com/course/data-structures-avl-trees/
  170. public sealed class AVLTree<Key, Value>
  171. {
  172. public int ElemCount { get; private set; }
  173. public int NodeCount { get; private set; }
  174. public IComparer<Key> Comparer;
  175. public Node<Key, Value> RootNode { get; private set; } = null;
  176. public AVLTree(IComparer<Key> comparer)
  177. {
  178. this.Comparer = comparer;
  179. }
  180. public void Add(Key key, Value item, bool clearValues = false)
  181. {
  182. if (this.RootNode == null) {
  183. this.NodeCount++;
  184. this.ElemCount++;
  185. this.RootNode = new Node<Key, Value>(null, key, item);
  186. return;
  187. }
  188. var current = this.RootNode;
  189. do
  190. {
  191. // +--------------------+-----------------------+
  192. // | Value | Meaning |
  193. // +--------------------+-----------------------+
  194. // | Less than zero | x is less than y. |
  195. // | Zero | x equals y. |
  196. // | Greater than zero | x is greater than y. |
  197. // +--------------------------------------------+
  198. int comp = this.Comparer.Compare(/*x: */ current.Key, /*y: */ key);
  199. // equals
  200. if (comp == 0)
  201. {
  202. if (clearValues)
  203. {
  204. this.ElemCount -= current.Count;
  205. current.Clear();
  206. }
  207. current.Add(item);
  208. break;
  209. }
  210. // current's key > key
  211. if (comp > 0)
  212. {
  213. // insert new node
  214. if (current.Left == null)
  215. {
  216. current.Left = new Node<Key, Value>(current, key, item);
  217. current.BubbleUpDepthChange(/*Side.Left, 1*/);
  218. current = current.Left;
  219. this.NodeCount++;
  220. break;
  221. }
  222. else
  223. {
  224. current = current.Left;
  225. continue;
  226. }
  227. }
  228. // current's key < key
  229. if (comp < 0)
  230. {
  231. // insert new node
  232. if (current.Right == null)
  233. {
  234. current.Right = new Node<Key, Value>(current, key, item);
  235. current.BubbleUpDepthChange(/*Side.Right, 1*/);
  236. current = current.Right;
  237. this.NodeCount++;
  238. break;
  239. }
  240. else
  241. {
  242. current = current.Right;
  243. continue;
  244. }
  245. }
  246. } while (true);
  247. this.ElemCount++;
  248. while (RebalanceFrom(current) != null)
  249. ;
  250. //TestBalance(this.root);
  251. }
  252. public bool TestBalance() => TestBalance(this.RootNode);
  253. private bool TestBalance(Node<Key, Value> node)
  254. {
  255. if (node == null)
  256. return true;
  257. if (Math.Abs(node.BalanceFactor) > 1)
  258. {
  259. //UnityEngine.Debug.Break();
  260. return false;
  261. }
  262. return TestBalance(node.Left) && TestBalance(node.Right);
  263. }
  264. List<Side> path = new List<Side>(2);
  265. private Node<Key, Value> RebalanceFrom(Node<Key, Value> newNode)
  266. {
  267. if (newNode.IsRoot || newNode.Parent.IsRoot)
  268. return null;
  269. path.Clear();
  270. // find first unbalanced node or exit when found the root node (root still can be unbalanced!)
  271. var current = newNode;
  272. var balanceFactor = current.BalanceFactor;
  273. while (!current.IsRoot && Math.Abs(balanceFactor) <= 1)
  274. {
  275. if (current.Parent.Left == current)
  276. path.Add(Side.Left);
  277. else
  278. path.Add(Side.Right);
  279. current = current.Parent;
  280. balanceFactor = current.BalanceFactor;
  281. }
  282. // it's a balanced tree
  283. if (Math.Abs(balanceFactor) <= 1)
  284. return null;
  285. Side last = path[path.Count - 1];// path[path.StartIdx];
  286. Side prev = path[path.Count - 2];// path[path.EndIdx];
  287. if (last == Side.Left && prev == Side.Left)
  288. {
  289. // insertion to a left child of a left child
  290. RotateRight(current)
  291. .BubbleUpDepthChange();
  292. current.BubbleUpDepthChange();
  293. }
  294. else if (last == Side.Right && prev == Side.Right)
  295. {
  296. // insertion to a right child of a right child
  297. RotateLeft(current)
  298. .BubbleUpDepthChange();
  299. current.BubbleUpDepthChange();
  300. }
  301. else if (last == Side.Right && prev == Side.Left)
  302. {
  303. // insertion to a left child of a right child
  304. var current_right = current.Right;
  305. RotateRight(current.Right);
  306. RotateLeft(current);
  307. current_right.BubbleUpDepthChange();
  308. current.BubbleUpDepthChange();
  309. }
  310. else if (last == Side.Left && prev == Side.Right)
  311. {
  312. // insertion to a right child of a left child
  313. var current_left = current.Left;
  314. RotateLeft(current.Left);
  315. RotateRight(current);
  316. current_left.BubbleUpDepthChange();
  317. current.BubbleUpDepthChange();
  318. }
  319. return current;
  320. }
  321. public void Clear()
  322. {
  323. this.RootNode = null;
  324. this.ElemCount = 0;
  325. this.NodeCount = 0;
  326. }
  327. public List<Value> Remove(Key key)
  328. {
  329. if (this.RootNode == null)
  330. return null;
  331. var current = this.RootNode;
  332. do
  333. {
  334. int comp = this.Comparer.Compare(current.Key, key);
  335. // equals
  336. if (comp == 0)
  337. {
  338. this.NodeCount--;
  339. this.ElemCount -= current.Count;
  340. // remove current node from the tree
  341. RemoveNode(current);
  342. return current.ToList();
  343. }
  344. // current's key > key
  345. if (comp > 0)
  346. {
  347. if (current.Left == null)
  348. return null;
  349. else
  350. {
  351. current = current.Left;
  352. continue;
  353. }
  354. }
  355. // current's key < key
  356. if (comp < 0)
  357. {
  358. if (current.Right == null)
  359. return null;
  360. else
  361. {
  362. current = current.Right;
  363. continue;
  364. }
  365. }
  366. } while (true);
  367. }
  368. public void Remove(Key key, Value value)
  369. {
  370. if (this.RootNode == null)
  371. return;
  372. var current = this.RootNode;
  373. do
  374. {
  375. int comp = this.Comparer.Compare(current.Key, key);
  376. // equals
  377. if (comp == 0)
  378. {
  379. if (current.Remove(value))
  380. this.ElemCount--;
  381. if (current.Count == 0)
  382. {
  383. // remove current node from the tree
  384. RemoveNode(current);
  385. this.NodeCount--;
  386. }
  387. return;
  388. }
  389. // current's key > key
  390. if (comp > 0)
  391. {
  392. if (current.Left == null)
  393. return ;
  394. else
  395. {
  396. current = current.Left;
  397. continue;
  398. }
  399. }
  400. // current's key < key
  401. if (comp < 0)
  402. {
  403. if (current.Right == null)
  404. return ;
  405. else
  406. {
  407. current = current.Right;
  408. continue;
  409. }
  410. }
  411. } while (true);
  412. }
  413. /// <summary>
  414. /// Removes node and reparent any child it has.
  415. /// </summary>
  416. private void RemoveNode(Node<Key, Value> node)
  417. {
  418. var parent = node.Parent;
  419. Side side = parent?.Left == node ? Side.Left : Side.Right;
  420. int childCount = node.ChildCount;
  421. var testForRebalanceNode = parent;
  422. switch(childCount)
  423. {
  424. case 0:
  425. // node has no child
  426. if (parent == null)
  427. {
  428. this.RootNode = null;
  429. }
  430. else
  431. {
  432. if (parent.Left == node)
  433. parent.Left = null;
  434. else
  435. parent.Right = null;
  436. parent.BubbleUpDepthChange();
  437. }
  438. node.Parent = null;
  439. break;
  440. case 1:
  441. // re-parent the only child
  442. // Example: Removing node 25 will replace it with 30
  443. //
  444. // 20
  445. // 15 25
  446. // 30
  447. //
  448. var child = node.Left ?? node.Right;
  449. if (parent == null)
  450. {
  451. this.RootNode = child;
  452. this.RootNode.Parent = null;
  453. }
  454. else
  455. {
  456. if (parent.Left == node)
  457. parent.Left = child;
  458. else
  459. parent.Right = child;
  460. child.Parent = parent;
  461. parent.BubbleUpDepthChange();
  462. }
  463. break;
  464. default:
  465. // two child
  466. // 1: Replace 20 with 25
  467. //
  468. // 20 20
  469. // 15 25 15 25
  470. // 30
  471. //
  472. // 2: Replace 20 with 22
  473. //
  474. // 20
  475. // 15 25
  476. // 22
  477. // 3: Re-parent 23 for 25, replace 20 with 22
  478. //
  479. // 20
  480. // 15 25
  481. // 22
  482. // 23
  483. // Cases 1 and 3 are the same, both 25 and 22 has a right child. But in case 3, 22 isn't first child of 20!
  484. // Find node with the least Key, that's a node without a left node so we have to deal only with its right node.
  485. var nodeToReplaceWith = FindMin(node.Right);
  486. testForRebalanceNode = nodeToReplaceWith;
  487. side = Side.Right;
  488. // re-parent 23 in case 3:
  489. if (nodeToReplaceWith.Parent != node)
  490. {
  491. testForRebalanceNode = nodeToReplaceWith.Parent;
  492. if (nodeToReplaceWith.Parent.Left == nodeToReplaceWith)
  493. {
  494. nodeToReplaceWith.Parent.Left = nodeToReplaceWith.Right;
  495. side = Side.Left;
  496. }
  497. else
  498. {
  499. nodeToReplaceWith.Parent.Right = nodeToReplaceWith.Right;
  500. side = Side.Right;
  501. }
  502. if (nodeToReplaceWith.Right != null)
  503. nodeToReplaceWith.Right.Parent = nodeToReplaceWith.Parent;
  504. }
  505. if (parent == null)
  506. this.RootNode = nodeToReplaceWith;
  507. else
  508. {
  509. if (parent.Left == node)
  510. parent.Left = nodeToReplaceWith;
  511. else
  512. parent.Right = nodeToReplaceWith;
  513. }
  514. nodeToReplaceWith.Parent = parent;
  515. // Reparent node's left
  516. nodeToReplaceWith.Left = node.Left;
  517. node.Left.Parent = nodeToReplaceWith;
  518. // Reparent node's right node, if it's not the one we replaceing it with
  519. if (node.Right != nodeToReplaceWith)
  520. {
  521. nodeToReplaceWith.Right = node.Right;
  522. node.Right.Parent = nodeToReplaceWith;
  523. }
  524. //else
  525. // nodeToReplaceWith.Right = null;
  526. if (testForRebalanceNode != nodeToReplaceWith)
  527. testForRebalanceNode.BubbleUpDepthChange();
  528. nodeToReplaceWith.BubbleUpDepthChange();
  529. break;
  530. }
  531. while (RebalanceForRemoval(testForRebalanceNode, side) != null)
  532. ;
  533. //TestBalance(this.root);
  534. }
  535. private Node<Key, Value> RebalanceForRemoval(Node<Key, Value> removedParentNode, Side side)
  536. {
  537. if (removedParentNode == null)
  538. return null;
  539. path.Clear();
  540. path.Add(side);
  541. // find first unbalanced node or exit when found the root node (root still can be unbalanced!)
  542. var current = removedParentNode;
  543. while (!current.IsRoot && Math.Abs(current.BalanceFactor) <= 1)
  544. {
  545. if (current.Parent.Left == current)
  546. path.Add(Side.Left);
  547. else
  548. path.Add(Side.Right);
  549. current = current.Parent;
  550. }
  551. // it's a balanced tree
  552. if (Math.Abs(current.BalanceFactor) <= 1)
  553. return null;
  554. // from what direction we came from
  555. Side fromDirection = path[path.Count - 1];
  556. // check weather it's an inside or outside case
  557. switch (fromDirection)
  558. {
  559. case Side.Right:
  560. {
  561. bool isOutside = current.Left.LeftDepth >= current.Left.RightDepth;
  562. if (isOutside)
  563. {
  564. RotateRight(current)
  565. .BubbleUpDepthChange();
  566. current.BubbleUpDepthChange();
  567. }
  568. else
  569. {
  570. var current_left = current.Left;
  571. RotateLeft(current.Left);
  572. RotateRight(current);
  573. current_left.BubbleUpDepthChange();
  574. current.BubbleUpDepthChange();
  575. }
  576. }
  577. break;
  578. case Side.Left:
  579. {
  580. bool isOutside = current.Right.RightDepth >= current.Right.LeftDepth;
  581. if (isOutside)
  582. {
  583. // Example: Removing node 14 result in a disbalance in node 20
  584. //
  585. // 20
  586. // 15 25
  587. // (14) 22 26
  588. // 27
  589. var current_right = current.Right; // node 25
  590. RotateLeft(current);
  591. // After RotateLeft(current: node 20):
  592. // 25
  593. // 20 26
  594. // 15 22 27
  595. current.BubbleUpDepthChange(); // node 20
  596. current_right.BubbleUpDepthChange(); // node 25
  597. }
  598. else
  599. {
  600. // Example: Removing node 14 results in a disbalance in node 20.
  601. //
  602. // 20
  603. // 15 25
  604. // (14) 22 26
  605. // 23
  606. var current_right = current.Right;
  607. RotateRight(current.Right);
  608. // After RotateRight(current.Right: node 22):
  609. // 20
  610. // 15 22
  611. // 25
  612. // 23 26
  613. RotateLeft(current);
  614. // After RotateLeft(current: node 20):
  615. // 22
  616. // 20 25
  617. // 15 23 26
  618. current.BubbleUpDepthChange();
  619. current_right.BubbleUpDepthChange();
  620. }
  621. }
  622. break;
  623. }
  624. return current;
  625. }
  626. private Node<Key, Value> FindMin(Node<Key, Value> node)
  627. {
  628. var current = node;
  629. while (current.Left != null)
  630. current = current.Left;
  631. return current;
  632. }
  633. private Node<Key, Value> FindMax(Node<Key, Value> node)
  634. {
  635. var current = node;
  636. while (current.Right != null)
  637. current = current.Right;
  638. return current;
  639. }
  640. public List<Value> Find(Key key) {
  641. if (this.RootNode == null)
  642. return null;
  643. var current = this.RootNode;
  644. do
  645. {
  646. int comp = this.Comparer.Compare(current.Key, key);
  647. // equals
  648. if (comp == 0)
  649. return current.ToList();
  650. // current's key > key
  651. if (comp > 0)
  652. {
  653. if (current.Left == null)
  654. return null;
  655. else
  656. {
  657. current = current.Left;
  658. continue;
  659. }
  660. }
  661. // current's key < key
  662. if (comp < 0)
  663. {
  664. if (current.Right == null)
  665. return null;
  666. else
  667. {
  668. current = current.Right;
  669. continue;
  670. }
  671. }
  672. } while (true);
  673. }
  674. public IEnumerable<Value> WalkHorizontal()
  675. {
  676. if (this.RootNode == null)
  677. yield break;
  678. Queue<Node<Key, Value>> toWalk = new Queue<Node<Key, Value>>();
  679. toWalk.Enqueue(this.RootNode);
  680. while (toWalk.Count > 0)
  681. {
  682. var current = toWalk.Dequeue();
  683. if (current.Left != null)
  684. toWalk.Enqueue(current.Left);
  685. if (current.Right != null)
  686. toWalk.Enqueue(current.Right);
  687. for (int i = 0; i < current.Count; i++)
  688. yield return current[i];
  689. }
  690. }
  691. public bool ContainsKey(Key key)
  692. {
  693. if (this.RootNode == null)
  694. return false;
  695. var current = this.RootNode;
  696. do
  697. {
  698. int comp = this.Comparer.Compare(current.Key, key);
  699. // equals
  700. if (comp == 0)
  701. return true;
  702. // current's key > key
  703. if (comp > 0)
  704. {
  705. if (current.Left == null)
  706. return false;
  707. else
  708. {
  709. current = current.Left;
  710. continue;
  711. }
  712. }
  713. // current's key < key
  714. if (comp < 0)
  715. {
  716. if (current.Right == null)
  717. return false;
  718. else
  719. {
  720. current = current.Right;
  721. continue;
  722. }
  723. }
  724. } while (true);
  725. }
  726. private Node<Key, Value> RotateRight(Node<Key, Value> current)
  727. {
  728. // Current\
  729. // 20 15
  730. // 15 10 20
  731. // 10 ? ?
  732. var parent = current.Parent;
  733. var leftChild = current.Left;
  734. // re-parent left child
  735. if (parent != null)
  736. {
  737. if (parent.Left == current)
  738. parent.Left = leftChild;
  739. else
  740. parent.Right = leftChild;
  741. }
  742. else
  743. this.RootNode = leftChild;
  744. leftChild.Parent = parent;
  745. // re-parent left child's right child
  746. if (leftChild.Right != null)
  747. leftChild.Right.Parent = current;
  748. current.Left = leftChild.Right;
  749. // re-parent current
  750. current.Parent = leftChild;
  751. leftChild.Right = current;
  752. // return with the node that took the place of current
  753. return leftChild;
  754. }
  755. private Node<Key, Value> RotateLeft(Node<Key, Value> current)
  756. {
  757. // /Current
  758. // 20 15
  759. // 15 20 10
  760. // ? 10 ?
  761. var parent = current.Parent;
  762. var rightChild = current.Right;
  763. // re-parent right child
  764. if (parent != null)
  765. {
  766. if (parent.Left == current)
  767. parent.Left = rightChild;
  768. else
  769. parent.Right = rightChild;
  770. }
  771. else
  772. this.RootNode = rightChild;
  773. rightChild.Parent = parent;
  774. // re-parent right child's left child
  775. if (rightChild.Left != null)
  776. rightChild.Left.Parent = current;
  777. current.Right = rightChild.Left;
  778. // re-parent current
  779. current.Parent = rightChild;
  780. rightChild.Left = current;
  781. return rightChild;
  782. }
  783. }
  784. }