avltree.js 25 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892
  1. // Copyright 2007 The Closure Library Authors. All Rights Reserved.
  2. //
  3. // Licensed under the Apache License, Version 2.0 (the "License");
  4. // you may not use this file except in compliance with the License.
  5. // You may obtain a copy of the License at
  6. //
  7. // http://www.apache.org/licenses/LICENSE-2.0
  8. //
  9. // Unless required by applicable law or agreed to in writing, software
  10. // distributed under the License is distributed on an "AS-IS" BASIS,
  11. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. // See the License for the specific language governing permissions and
  13. // limitations under the License.
  14. /**
  15. * @fileoverview Datastructure: AvlTree.
  16. *
  17. *
  18. * This file provides the implementation of an AVL-Tree datastructure. The tree
  19. * maintains a set of unique values in a sorted order. The values can be
  20. * accessed efficiently in their sorted order since the tree enforces an O(logn)
  21. * maximum height. See http://en.wikipedia.org/wiki/Avl_tree for more detail.
  22. *
  23. * The big-O notation for all operations are below:
  24. * <pre>
  25. * Method big-O
  26. * ----------------------------------------------------------------------------
  27. * - add O(logn)
  28. * - remove O(logn)
  29. * - clear O(1)
  30. * - contains O(logn)
  31. * - indexOf O(logn)
  32. * - getCount O(1)
  33. * - getMinimum O(1), or O(logn) when optional root is specified
  34. * - getMaximum O(1), or O(logn) when optional root is specified
  35. * - getHeight O(1)
  36. * - getValues O(n)
  37. * - inOrderTraverse O(logn + k), where k is number of traversed nodes
  38. * - reverseOrderTraverse O(logn + k), where k is number of traversed nodes
  39. * </pre>
  40. */
  41. goog.provide('goog.structs.AvlTree');
  42. goog.provide('goog.structs.AvlTree.Node');
  43. goog.require('goog.structs.Collection');
  44. /**
  45. * Constructs an AVL-Tree, which uses the specified comparator to order its
  46. * values. The values can be accessed efficiently in their sorted order since
  47. * the tree enforces a O(logn) maximum height.
  48. *
  49. * @param {Function=} opt_comparator Function used to order the tree's nodes.
  50. * @constructor
  51. * @implements {goog.structs.Collection<T>}
  52. * @final
  53. * @template T
  54. */
  55. goog.structs.AvlTree = function(opt_comparator) {
  56. this.comparator_ = opt_comparator || goog.structs.AvlTree.DEFAULT_COMPARATOR_;
  57. };
  58. /**
  59. * String comparison function used to compare values in the tree. This function
  60. * is used by default if no comparator is specified in the tree's constructor.
  61. *
  62. * @param {T} a The first value.
  63. * @param {T} b The second value.
  64. * @return {number} -1 if a < b, 1 if a > b, 0 if a = b.
  65. * @template T
  66. * @private
  67. */
  68. goog.structs.AvlTree.DEFAULT_COMPARATOR_ = function(a, b) {
  69. if (String(a) < String(b)) {
  70. return -1;
  71. } else if (String(a) > String(b)) {
  72. return 1;
  73. }
  74. return 0;
  75. };
  76. /**
  77. * Pointer to the root node of the tree.
  78. *
  79. * @private {goog.structs.AvlTree.Node<T>}
  80. */
  81. goog.structs.AvlTree.prototype.root_ = null;
  82. /**
  83. * Comparison function used to compare values in the tree. This function should
  84. * take two values, a and b, and return x where:
  85. * <pre>
  86. * x < 0 if a < b,
  87. * x > 0 if a > b,
  88. * x = 0 otherwise
  89. * </pre>
  90. *
  91. * @type {Function}
  92. * @private
  93. */
  94. goog.structs.AvlTree.prototype.comparator_ = null;
  95. /**
  96. * Pointer to the node with the smallest value in the tree.
  97. *
  98. * @type {goog.structs.AvlTree.Node<T>}
  99. * @private
  100. */
  101. goog.structs.AvlTree.prototype.minNode_ = null;
  102. /**
  103. * Pointer to the node with the largest value in the tree.
  104. *
  105. * @type {goog.structs.AvlTree.Node<T>}
  106. * @private
  107. */
  108. goog.structs.AvlTree.prototype.maxNode_ = null;
  109. /**
  110. * Inserts a node into the tree with the specified value if the tree does
  111. * not already contain a node with the specified value. If the value is
  112. * inserted, the tree is balanced to enforce the AVL-Tree height property.
  113. *
  114. * @param {T} value Value to insert into the tree.
  115. * @return {boolean} Whether value was inserted into the tree.
  116. * @override
  117. */
  118. goog.structs.AvlTree.prototype.add = function(value) {
  119. // If the tree is empty, create a root node with the specified value
  120. if (this.root_ == null) {
  121. this.root_ = new goog.structs.AvlTree.Node(value);
  122. this.minNode_ = this.root_;
  123. this.maxNode_ = this.root_;
  124. return true;
  125. }
  126. // This will be set to the new node if a new node is added.
  127. var newNode = null;
  128. // Depth traverse the tree and insert the value if we reach a null node
  129. this.traverse_(function(node) {
  130. var retNode = null;
  131. var comparison = this.comparator_(node.value, value);
  132. if (comparison > 0) {
  133. retNode = node.left;
  134. if (node.left == null) {
  135. newNode = new goog.structs.AvlTree.Node(value, node);
  136. node.left = newNode;
  137. if (node == this.minNode_) {
  138. this.minNode_ = newNode;
  139. }
  140. }
  141. } else if (comparison < 0) {
  142. retNode = node.right;
  143. if (node.right == null) {
  144. newNode = new goog.structs.AvlTree.Node(value, node);
  145. node.right = newNode;
  146. if (node == this.maxNode_) {
  147. this.maxNode_ = newNode;
  148. }
  149. }
  150. }
  151. return retNode; // If null, we'll stop traversing the tree
  152. });
  153. // If a node was added, increment counts and balance tree.
  154. if (newNode) {
  155. this.traverse_(function(node) {
  156. node.count++;
  157. return node.parent;
  158. }, newNode.parent);
  159. this.balance_(newNode.parent); // Maintain the AVL-tree balance
  160. }
  161. // Return true if a node was added, false otherwise
  162. return !!newNode;
  163. };
  164. /**
  165. * Removes a node from the tree with the specified value if the tree contains a
  166. * node with this value. If a node is removed the tree is balanced to enforce
  167. * the AVL-Tree height property. The value of the removed node is returned.
  168. *
  169. * @param {T} value Value to find and remove from the tree.
  170. * @return {T} The value of the removed node or null if the value was not in
  171. * the tree.
  172. * @override
  173. */
  174. goog.structs.AvlTree.prototype.remove = function(value) {
  175. // Assume the value is not removed and set the value when it is removed
  176. var retValue = null;
  177. // Depth traverse the tree and remove the value if we find it
  178. this.traverse_(function(node) {
  179. var retNode = null;
  180. var comparison = this.comparator_(node.value, value);
  181. if (comparison > 0) {
  182. retNode = node.left;
  183. } else if (comparison < 0) {
  184. retNode = node.right;
  185. } else {
  186. retValue = node.value;
  187. this.removeNode_(node);
  188. }
  189. return retNode; // If null, we'll stop traversing the tree
  190. });
  191. // Return the value that was removed, null if the value was not in the tree
  192. return retValue;
  193. };
  194. /**
  195. * Removes all nodes from the tree.
  196. */
  197. goog.structs.AvlTree.prototype.clear = function() {
  198. this.root_ = null;
  199. this.minNode_ = null;
  200. this.maxNode_ = null;
  201. };
  202. /**
  203. * Returns true if the tree contains a node with the specified value, false
  204. * otherwise.
  205. *
  206. * @param {T} value Value to find in the tree.
  207. * @return {boolean} Whether the tree contains a node with the specified value.
  208. * @override
  209. */
  210. goog.structs.AvlTree.prototype.contains = function(value) {
  211. // Assume the value is not in the tree and set this value if it is found
  212. var isContained = false;
  213. // Depth traverse the tree and set isContained if we find the node
  214. this.traverse_(function(node) {
  215. var retNode = null;
  216. var comparison = this.comparator_(node.value, value);
  217. if (comparison > 0) {
  218. retNode = node.left;
  219. } else if (comparison < 0) {
  220. retNode = node.right;
  221. } else {
  222. isContained = true;
  223. }
  224. return retNode; // If null, we'll stop traversing the tree
  225. });
  226. // Return true if the value is contained in the tree, false otherwise
  227. return isContained;
  228. };
  229. /**
  230. * Returns the index (in an in-order traversal) of the node in the tree with
  231. * the specified value. For example, the minimum value in the tree will
  232. * return an index of 0 and the maximum will return an index of n - 1 (where
  233. * n is the number of nodes in the tree). If the value is not found then -1
  234. * is returned.
  235. *
  236. * @param {T} value Value in the tree whose in-order index is returned.
  237. * @return {number} The in-order index of the given value in the
  238. * tree or -1 if the value is not found.
  239. */
  240. goog.structs.AvlTree.prototype.indexOf = function(value) {
  241. // Assume the value is not in the tree and set this value if it is found
  242. var retIndex = -1;
  243. var currIndex = 0;
  244. // Depth traverse the tree and set retIndex if we find the node
  245. this.traverse_(function(node) {
  246. var comparison = this.comparator_(node.value, value);
  247. if (comparison > 0) {
  248. // The value is less than this node, so recurse into the left subtree.
  249. return node.left;
  250. }
  251. if (node.left) {
  252. // The value is greater than all of the nodes in the left subtree.
  253. currIndex += node.left.count;
  254. }
  255. if (comparison < 0) {
  256. // The value is also greater than this node.
  257. currIndex++;
  258. // Recurse into the right subtree.
  259. return node.right;
  260. }
  261. // We found the node, so stop traversing the tree.
  262. retIndex = currIndex;
  263. return null;
  264. });
  265. // Return index if the value is contained in the tree, -1 otherwise
  266. return retIndex;
  267. };
  268. /**
  269. * Returns the number of values stored in the tree.
  270. *
  271. * @return {number} The number of values stored in the tree.
  272. * @override
  273. */
  274. goog.structs.AvlTree.prototype.getCount = function() {
  275. return this.root_ ? this.root_.count : 0;
  276. };
  277. /**
  278. * Returns a k-th smallest value, based on the comparator, where 0 <= k <
  279. * this.getCount().
  280. * @param {number} k The number k.
  281. * @return {T} The k-th smallest value.
  282. */
  283. goog.structs.AvlTree.prototype.getKthValue = function(k) {
  284. if (k < 0 || k >= this.getCount()) {
  285. return null;
  286. }
  287. return this.getKthNode_(k).value;
  288. };
  289. /**
  290. * Returns the value u, such that u is contained in the tree and u < v, for all
  291. * values v in the tree where v != u.
  292. *
  293. * @return {T} The minimum value contained in the tree.
  294. */
  295. goog.structs.AvlTree.prototype.getMinimum = function() {
  296. return this.getMinNode_().value;
  297. };
  298. /**
  299. * Returns the value u, such that u is contained in the tree and u > v, for all
  300. * values v in the tree where v != u.
  301. *
  302. * @return {T} The maximum value contained in the tree.
  303. */
  304. goog.structs.AvlTree.prototype.getMaximum = function() {
  305. return this.getMaxNode_().value;
  306. };
  307. /**
  308. * Returns the height of the tree (the maximum depth). This height should
  309. * always be <= 1.4405*(Math.log(n+2)/Math.log(2))-1.3277, where n is the
  310. * number of nodes in the tree.
  311. *
  312. * @return {number} The height of the tree.
  313. */
  314. goog.structs.AvlTree.prototype.getHeight = function() {
  315. return this.root_ ? this.root_.height : 0;
  316. };
  317. /**
  318. * Inserts the values stored in the tree into a new Array and returns the Array.
  319. *
  320. * @return {!Array<T>} An array containing all of the trees values in sorted
  321. * order.
  322. */
  323. goog.structs.AvlTree.prototype.getValues = function() {
  324. var ret = [];
  325. this.inOrderTraverse(function(value) { ret.push(value); });
  326. return ret;
  327. };
  328. /**
  329. * Performs an in-order traversal of the tree and calls {@code func} with each
  330. * traversed node, optionally starting from the smallest node with a value >= to
  331. * the specified start value. The traversal ends after traversing the tree's
  332. * maximum node or when {@code func} returns a value that evaluates to true.
  333. *
  334. * @param {Function} func Function to call on each traversed node.
  335. * @param {T=} opt_startValue If specified, traversal will begin on the node
  336. * with the smallest value >= opt_startValue.
  337. */
  338. goog.structs.AvlTree.prototype.inOrderTraverse = function(
  339. func, opt_startValue) {
  340. // If our tree is empty, return immediately
  341. if (!this.root_) {
  342. return;
  343. }
  344. // Depth traverse the tree to find node to begin in-order traversal from
  345. var startNode;
  346. if (opt_startValue !== undefined) {
  347. this.traverse_(function(node) {
  348. var retNode = null;
  349. var comparison = this.comparator_(node.value, opt_startValue);
  350. if (comparison > 0) {
  351. retNode = node.left;
  352. startNode = node;
  353. } else if (comparison < 0) {
  354. retNode = node.right;
  355. } else {
  356. startNode = node;
  357. }
  358. return retNode; // If null, we'll stop traversing the tree
  359. });
  360. if (!startNode) {
  361. return;
  362. }
  363. } else {
  364. startNode = this.getMinNode_();
  365. }
  366. // Traverse the tree and call func on each traversed node's value
  367. var node = startNode, prev = startNode.left ? startNode.left : startNode;
  368. while (node != null) {
  369. if (node.left != null && node.left != prev && node.right != prev) {
  370. node = node.left;
  371. } else {
  372. if (node.right != prev) {
  373. if (func(node.value)) {
  374. return;
  375. }
  376. }
  377. var temp = node;
  378. node =
  379. node.right != null && node.right != prev ? node.right : node.parent;
  380. prev = temp;
  381. }
  382. }
  383. };
  384. /**
  385. * Performs a reverse-order traversal of the tree and calls {@code func} with
  386. * each traversed node, optionally starting from the largest node with a value
  387. * <= to the specified start value. The traversal ends after traversing the
  388. * tree's minimum node or when func returns a value that evaluates to true.
  389. *
  390. * @param {function(T):?} func Function to call on each traversed node.
  391. * @param {T=} opt_startValue If specified, traversal will begin on the node
  392. * with the largest value <= opt_startValue.
  393. */
  394. goog.structs.AvlTree.prototype.reverseOrderTraverse = function(
  395. func, opt_startValue) {
  396. // If our tree is empty, return immediately
  397. if (!this.root_) {
  398. return;
  399. }
  400. // Depth traverse the tree to find node to begin reverse-order traversal from
  401. var startNode;
  402. if (opt_startValue !== undefined) {
  403. this.traverse_(goog.bind(function(node) {
  404. var retNode = null;
  405. var comparison = this.comparator_(node.value, opt_startValue);
  406. if (comparison > 0) {
  407. retNode = node.left;
  408. } else if (comparison < 0) {
  409. retNode = node.right;
  410. startNode = node;
  411. } else {
  412. startNode = node;
  413. }
  414. return retNode; // If null, we'll stop traversing the tree
  415. }, this));
  416. if (!startNode) {
  417. return;
  418. }
  419. } else {
  420. startNode = this.getMaxNode_();
  421. }
  422. // Traverse the tree and call func on each traversed node's value
  423. var node = startNode, prev = startNode.right ? startNode.right : startNode;
  424. while (node != null) {
  425. if (node.right != null && node.right != prev && node.left != prev) {
  426. node = node.right;
  427. } else {
  428. if (node.left != prev) {
  429. if (func(node.value)) {
  430. return;
  431. }
  432. }
  433. var temp = node;
  434. node = node.left != null && node.left != prev ? node.left : node.parent;
  435. prev = temp;
  436. }
  437. }
  438. };
  439. /**
  440. * Performs a traversal defined by the supplied {@code traversalFunc}. The first
  441. * call to {@code traversalFunc} is passed the root or the optionally specified
  442. * startNode. After that, calls {@code traversalFunc} with the node returned
  443. * by the previous call to {@code traversalFunc} until {@code traversalFunc}
  444. * returns null or the optionally specified endNode. The first call to
  445. * traversalFunc is passed the root or the optionally specified startNode.
  446. *
  447. * @param {function(
  448. * this:goog.structs.AvlTree<T>,
  449. * !goog.structs.AvlTree.Node):?goog.structs.AvlTree.Node} traversalFunc
  450. * Function used to traverse the tree.
  451. * @param {goog.structs.AvlTree.Node<T>=} opt_startNode The node at which the
  452. * traversal begins.
  453. * @param {goog.structs.AvlTree.Node<T>=} opt_endNode The node at which the
  454. * traversal ends.
  455. * @private
  456. */
  457. goog.structs.AvlTree.prototype.traverse_ = function(
  458. traversalFunc, opt_startNode, opt_endNode) {
  459. var node = opt_startNode ? opt_startNode : this.root_;
  460. var endNode = opt_endNode ? opt_endNode : null;
  461. while (node && node != endNode) {
  462. node = traversalFunc.call(this, node);
  463. }
  464. };
  465. /**
  466. * Ensures that the specified node and all its ancestors are balanced. If they
  467. * are not, performs left and right tree rotations to achieve a balanced
  468. * tree. This method assumes that at most 2 rotations are necessary to balance
  469. * the tree (which is true for AVL-trees that are balanced after each node is
  470. * added or removed).
  471. *
  472. * @param {goog.structs.AvlTree.Node<T>} node Node to begin balance from.
  473. * @private
  474. */
  475. goog.structs.AvlTree.prototype.balance_ = function(node) {
  476. this.traverse_(function(node) {
  477. // Calculate the left and right node's heights
  478. var lh = node.left ? node.left.height : 0;
  479. var rh = node.right ? node.right.height : 0;
  480. // Rotate tree rooted at this node if it is not AVL-tree balanced
  481. if (lh - rh > 1) {
  482. if (node.left.right &&
  483. (!node.left.left || node.left.left.height < node.left.right.height)) {
  484. this.leftRotate_(node.left);
  485. }
  486. this.rightRotate_(node);
  487. } else if (rh - lh > 1) {
  488. if (node.right.left &&
  489. (!node.right.right ||
  490. node.right.right.height < node.right.left.height)) {
  491. this.rightRotate_(node.right);
  492. }
  493. this.leftRotate_(node);
  494. }
  495. // Recalculate the left and right node's heights
  496. lh = node.left ? node.left.height : 0;
  497. rh = node.right ? node.right.height : 0;
  498. // Set this node's height
  499. node.height = Math.max(lh, rh) + 1;
  500. // Traverse up tree and balance parent
  501. return node.parent;
  502. }, node);
  503. };
  504. /**
  505. * Performs a left tree rotation on the specified node.
  506. *
  507. * @param {goog.structs.AvlTree.Node<T>} node Pivot node to rotate from.
  508. * @private
  509. */
  510. goog.structs.AvlTree.prototype.leftRotate_ = function(node) {
  511. // Re-assign parent-child references for the parent of the node being removed
  512. if (node.isLeftChild()) {
  513. node.parent.left = node.right;
  514. node.right.parent = node.parent;
  515. } else if (node.isRightChild()) {
  516. node.parent.right = node.right;
  517. node.right.parent = node.parent;
  518. } else {
  519. this.root_ = node.right;
  520. this.root_.parent = null;
  521. }
  522. // Re-assign parent-child references for the child of the node being removed
  523. var temp = node.right;
  524. node.right = node.right.left;
  525. if (node.right != null) node.right.parent = node;
  526. temp.left = node;
  527. node.parent = temp;
  528. // Update counts.
  529. temp.count = node.count;
  530. node.count -= (temp.right ? temp.right.count : 0) + 1;
  531. };
  532. /**
  533. * Performs a right tree rotation on the specified node.
  534. *
  535. * @param {goog.structs.AvlTree.Node<T>} node Pivot node to rotate from.
  536. * @private
  537. */
  538. goog.structs.AvlTree.prototype.rightRotate_ = function(node) {
  539. // Re-assign parent-child references for the parent of the node being removed
  540. if (node.isLeftChild()) {
  541. node.parent.left = node.left;
  542. node.left.parent = node.parent;
  543. } else if (node.isRightChild()) {
  544. node.parent.right = node.left;
  545. node.left.parent = node.parent;
  546. } else {
  547. this.root_ = node.left;
  548. this.root_.parent = null;
  549. }
  550. // Re-assign parent-child references for the child of the node being removed
  551. var temp = node.left;
  552. node.left = node.left.right;
  553. if (node.left != null) node.left.parent = node;
  554. temp.right = node;
  555. node.parent = temp;
  556. // Update counts.
  557. temp.count = node.count;
  558. node.count -= (temp.left ? temp.left.count : 0) + 1;
  559. };
  560. /**
  561. * Removes the specified node from the tree and ensures the tree still
  562. * maintains the AVL-tree balance.
  563. *
  564. * @param {goog.structs.AvlTree.Node<T>} node The node to be removed.
  565. * @private
  566. */
  567. goog.structs.AvlTree.prototype.removeNode_ = function(node) {
  568. // Perform normal binary tree node removal, but balance the tree, starting
  569. // from where we removed the node
  570. if (node.left != null || node.right != null) {
  571. var b = null; // Node to begin balance from
  572. var r; // Node to replace the node being removed
  573. if (node.left != null) {
  574. r = this.getMaxNode_(node.left);
  575. // Update counts.
  576. this.traverse_(function(node) {
  577. node.count--;
  578. return node.parent;
  579. }, r);
  580. if (r != node.left) {
  581. r.parent.right = r.left;
  582. if (r.left) r.left.parent = r.parent;
  583. r.left = node.left;
  584. r.left.parent = r;
  585. b = r.parent;
  586. }
  587. r.parent = node.parent;
  588. r.right = node.right;
  589. if (r.right) r.right.parent = r;
  590. if (node == this.maxNode_) this.maxNode_ = r;
  591. r.count = node.count;
  592. } else {
  593. r = this.getMinNode_(node.right);
  594. // Update counts.
  595. this.traverse_(function(node) {
  596. node.count--;
  597. return node.parent;
  598. }, r);
  599. if (r != node.right) {
  600. r.parent.left = r.right;
  601. if (r.right) r.right.parent = r.parent;
  602. r.right = node.right;
  603. r.right.parent = r;
  604. b = r.parent;
  605. }
  606. r.parent = node.parent;
  607. r.left = node.left;
  608. if (r.left) r.left.parent = r;
  609. if (node == this.minNode_) this.minNode_ = r;
  610. r.count = node.count;
  611. }
  612. // Update the parent of the node being removed to point to its replace
  613. if (node.isLeftChild()) {
  614. node.parent.left = r;
  615. } else if (node.isRightChild()) {
  616. node.parent.right = r;
  617. } else {
  618. this.root_ = r;
  619. }
  620. // Balance the tree
  621. this.balance_(b ? b : r);
  622. } else {
  623. // Update counts.
  624. this.traverse_(function(node) {
  625. node.count--;
  626. return node.parent;
  627. }, node.parent);
  628. // If the node is a leaf, remove it and balance starting from its parent
  629. if (node.isLeftChild()) {
  630. this.special = 1;
  631. node.parent.left = null;
  632. if (node == this.minNode_) this.minNode_ = node.parent;
  633. this.balance_(node.parent);
  634. } else if (node.isRightChild()) {
  635. node.parent.right = null;
  636. if (node == this.maxNode_) this.maxNode_ = node.parent;
  637. this.balance_(node.parent);
  638. } else {
  639. this.clear();
  640. }
  641. }
  642. };
  643. /**
  644. * Returns the node in the tree that has k nodes before it in an in-order
  645. * traversal, optionally rooted at {@code opt_rootNode}.
  646. *
  647. * @param {number} k The number of nodes before the node to be returned in an
  648. * in-order traversal, where 0 <= k < root.count.
  649. * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
  650. * @return {goog.structs.AvlTree.Node<T>} The node at the specified index.
  651. * @private
  652. */
  653. goog.structs.AvlTree.prototype.getKthNode_ = function(k, opt_rootNode) {
  654. var root = opt_rootNode || this.root_;
  655. var numNodesInLeftSubtree = root.left ? root.left.count : 0;
  656. if (k < numNodesInLeftSubtree) {
  657. return this.getKthNode_(k, root.left);
  658. } else if (k == numNodesInLeftSubtree) {
  659. return root;
  660. } else {
  661. return this.getKthNode_(k - numNodesInLeftSubtree - 1, root.right);
  662. }
  663. };
  664. /**
  665. * Returns the node with the smallest value in tree, optionally rooted at
  666. * {@code opt_rootNode}.
  667. *
  668. * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
  669. * @return {goog.structs.AvlTree.Node<T>} The node with the smallest value in
  670. * the tree.
  671. * @private
  672. */
  673. goog.structs.AvlTree.prototype.getMinNode_ = function(opt_rootNode) {
  674. if (!opt_rootNode) {
  675. return this.minNode_;
  676. }
  677. var minNode = opt_rootNode;
  678. this.traverse_(function(node) {
  679. var retNode = null;
  680. if (node.left) {
  681. minNode = node.left;
  682. retNode = node.left;
  683. }
  684. return retNode; // If null, we'll stop traversing the tree
  685. }, opt_rootNode);
  686. return minNode;
  687. };
  688. /**
  689. * Returns the node with the largest value in tree, optionally rooted at
  690. * opt_rootNode.
  691. *
  692. * @param {goog.structs.AvlTree.Node<T>=} opt_rootNode Optional root node.
  693. * @return {goog.structs.AvlTree.Node<T>} The node with the largest value in
  694. * the tree.
  695. * @private
  696. */
  697. goog.structs.AvlTree.prototype.getMaxNode_ = function(opt_rootNode) {
  698. if (!opt_rootNode) {
  699. return this.maxNode_;
  700. }
  701. var maxNode = opt_rootNode;
  702. this.traverse_(function(node) {
  703. var retNode = null;
  704. if (node.right) {
  705. maxNode = node.right;
  706. retNode = node.right;
  707. }
  708. return retNode; // If null, we'll stop traversing the tree
  709. }, opt_rootNode);
  710. return maxNode;
  711. };
  712. /**
  713. * Constructs an AVL-Tree node with the specified value. If no parent is
  714. * specified, the node's parent is assumed to be null. The node's height
  715. * defaults to 1 and its children default to null.
  716. *
  717. * @param {T} value Value to store in the node.
  718. * @param {goog.structs.AvlTree.Node<T>=} opt_parent Optional parent node.
  719. * @constructor
  720. * @final
  721. * @template T
  722. */
  723. goog.structs.AvlTree.Node = function(value, opt_parent) {
  724. /**
  725. * The value stored by the node.
  726. *
  727. * @type {T}
  728. */
  729. this.value = value;
  730. /**
  731. * The node's parent. Null if the node is the root.
  732. *
  733. * @type {goog.structs.AvlTree.Node<T>}
  734. */
  735. this.parent = opt_parent ? opt_parent : null;
  736. /**
  737. * The number of nodes in the subtree rooted at this node.
  738. *
  739. * @type {number}
  740. */
  741. this.count = 1;
  742. };
  743. /**
  744. * The node's left child. Null if the node does not have a left child.
  745. *
  746. * @type {?goog.structs.AvlTree.Node<T>}
  747. */
  748. goog.structs.AvlTree.Node.prototype.left = null;
  749. /**
  750. * The node's right child. Null if the node does not have a right child.
  751. *
  752. * @type {?goog.structs.AvlTree.Node<T>}
  753. */
  754. goog.structs.AvlTree.Node.prototype.right = null;
  755. /**
  756. * The height of the tree rooted at this node.
  757. *
  758. * @type {number}
  759. */
  760. goog.structs.AvlTree.Node.prototype.height = 1;
  761. /**
  762. * Returns true iff the specified node has a parent and is the right child of
  763. * its parent.
  764. *
  765. * @return {boolean} Whether the specified node has a parent and is the right
  766. * child of its parent.
  767. */
  768. goog.structs.AvlTree.Node.prototype.isRightChild = function() {
  769. return !!this.parent && this.parent.right == this;
  770. };
  771. /**
  772. * Returns true iff the specified node has a parent and is the left child of
  773. * its parent.
  774. *
  775. * @return {boolean} Whether the specified node has a parent and is the left
  776. * child of its parent.
  777. */
  778. goog.structs.AvlTree.Node.prototype.isLeftChild = function() {
  779. return !!this.parent && this.parent.left == this;
  780. };