avltree_test.js 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351
  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. goog.provide('goog.structs.AvlTreeTest');
  15. goog.setTestOnly('goog.structs.AvlTreeTest');
  16. goog.require('goog.array');
  17. goog.require('goog.structs.AvlTree');
  18. goog.require('goog.testing.jsunit');
  19. /**
  20. * This test verifies that we can insert strings into the AvlTree and have
  21. * them be stored and sorted correctly by the default comparator.
  22. */
  23. function testInsertsWithDefaultComparator() {
  24. var tree = new goog.structs.AvlTree();
  25. var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
  26. // Insert strings into tree out of order
  27. tree.add(values[4]);
  28. tree.add(values[3]);
  29. tree.add(values[0]);
  30. tree.add(values[6]);
  31. tree.add(values[5]);
  32. tree.add(values[1]);
  33. tree.add(values[2]);
  34. // Verify strings are stored in sorted order
  35. var i = 0;
  36. tree.inOrderTraverse(function(value) {
  37. assertEquals(values[i], value);
  38. i += 1;
  39. });
  40. assertEquals(i, values.length);
  41. // Verify that no nodes are visited if the start value is larger than all
  42. // values
  43. tree.inOrderTraverse(function(value) { fail(); }, 'zed');
  44. // Verify strings are stored in sorted order
  45. i = values.length;
  46. tree.reverseOrderTraverse(function(value) {
  47. i--;
  48. assertEquals(values[i], value);
  49. });
  50. assertEquals(i, 0);
  51. // Verify that no nodes are visited if the start value is smaller than all
  52. // values
  53. tree.reverseOrderTraverse(function(value) { fail(); }, 'aardvark');
  54. }
  55. /**
  56. * This test verifies that we can insert strings into and remove strings from
  57. * the AvlTree and have the only the non-removed values be stored and sorted
  58. * correctly by the default comparator.
  59. */
  60. function testRemovesWithDefaultComparator() {
  61. var tree = new goog.structs.AvlTree();
  62. var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
  63. // Insert strings into tree out of order
  64. tree.add('frodo');
  65. tree.add(values[4]);
  66. tree.add(values[3]);
  67. tree.add(values[0]);
  68. tree.add(values[6]);
  69. tree.add('samwise');
  70. tree.add(values[5]);
  71. tree.add(values[1]);
  72. tree.add(values[2]);
  73. tree.add('pippin');
  74. // Remove strings from tree
  75. assertEquals(tree.remove('samwise'), 'samwise');
  76. assertEquals(tree.remove('pippin'), 'pippin');
  77. assertEquals(tree.remove('frodo'), 'frodo');
  78. assertEquals(tree.remove('merry'), null);
  79. // Verify strings are stored in sorted order
  80. var i = 0;
  81. tree.inOrderTraverse(function(value) {
  82. assertEquals(values[i], value);
  83. i += 1;
  84. });
  85. assertEquals(i, values.length);
  86. }
  87. /**
  88. * This test verifies that we can insert values into and remove values from
  89. * the AvlTree and have them be stored and sorted correctly by a custom
  90. * comparator.
  91. */
  92. function testInsertsAndRemovesWithCustomComparator() {
  93. var tree = new goog.structs.AvlTree(function(a, b) { return a - b; });
  94. var NUM_TO_INSERT = 37;
  95. var valuesToRemove = [1, 0, 6, 7, 36];
  96. // Insert ints into tree out of order
  97. var values = [];
  98. for (var i = 0; i < NUM_TO_INSERT; i += 1) {
  99. tree.add(i);
  100. values.push(i);
  101. }
  102. for (var i = 0; i < valuesToRemove.length; i += 1) {
  103. assertEquals(tree.remove(valuesToRemove[i]), valuesToRemove[i]);
  104. goog.array.remove(values, valuesToRemove[i]);
  105. }
  106. assertEquals(tree.remove(-1), null);
  107. assertEquals(tree.remove(37), null);
  108. // Verify strings are stored in sorted order
  109. var i = 0;
  110. tree.inOrderTraverse(function(value) {
  111. assertEquals(values[i], value);
  112. i += 1;
  113. });
  114. assertEquals(i, values.length);
  115. }
  116. /**
  117. * This test verifies that we can insert values into and remove values from
  118. * the AvlTree and have it maintain the AVL-Tree upperbound on its height.
  119. */
  120. function testAvlTreeHeight() {
  121. var tree = new goog.structs.AvlTree(function(a, b) { return a - b; });
  122. var NUM_TO_INSERT = 2000;
  123. var NUM_TO_REMOVE = 500;
  124. // Insert ints into tree out of order
  125. for (var i = 0; i < NUM_TO_INSERT; i += 1) {
  126. tree.add(i);
  127. }
  128. // Remove valuse
  129. for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
  130. tree.remove(i);
  131. }
  132. assertTrue(
  133. tree.getHeight() <=
  134. 1.4405 * (Math.log(NUM_TO_INSERT - NUM_TO_REMOVE + 2) / Math.log(2)) -
  135. 1.3277);
  136. }
  137. /**
  138. * This test verifies that we can insert values into and remove values from
  139. * the AvlTree and have its contains method correctly determine the values it
  140. * is contains.
  141. */
  142. function testAvlTreeContains() {
  143. var tree = new goog.structs.AvlTree();
  144. var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
  145. // Insert strings into tree out of order
  146. tree.add('frodo');
  147. tree.add(values[4]);
  148. tree.add(values[3]);
  149. tree.add(values[0]);
  150. tree.add(values[6]);
  151. tree.add('samwise');
  152. tree.add(values[5]);
  153. tree.add(values[1]);
  154. tree.add(values[2]);
  155. tree.add('pippin');
  156. // Remove strings from tree
  157. assertEquals(tree.remove('samwise'), 'samwise');
  158. assertEquals(tree.remove('pippin'), 'pippin');
  159. assertEquals(tree.remove('frodo'), 'frodo');
  160. for (var i = 0; i < values.length; i += 1) {
  161. assertTrue(tree.contains(values[i]));
  162. }
  163. assertFalse(tree.contains('samwise'));
  164. assertFalse(tree.contains('pippin'));
  165. assertFalse(tree.contains('frodo'));
  166. }
  167. /**
  168. * This test verifies that we can insert values into and remove values from
  169. * the AvlTree and have its indexOf method correctly determine the in-order
  170. * index of the values it contains.
  171. */
  172. function testAvlTreeIndexOf() {
  173. var tree = new goog.structs.AvlTree();
  174. var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
  175. // Insert strings into tree out of order
  176. tree.add('frodo');
  177. tree.add(values[4]);
  178. tree.add(values[3]);
  179. tree.add(values[0]);
  180. tree.add(values[6]);
  181. tree.add('samwise');
  182. tree.add(values[5]);
  183. tree.add(values[1]);
  184. tree.add(values[2]);
  185. tree.add('pippin');
  186. // Remove strings from tree
  187. assertEquals('samwise', tree.remove('samwise'));
  188. assertEquals('pippin', tree.remove('pippin'));
  189. assertEquals('frodo', tree.remove('frodo'));
  190. for (var i = 0; i < values.length; i += 1) {
  191. assertEquals(i, tree.indexOf(values[i]));
  192. }
  193. assertEquals(-1, tree.indexOf('samwise'));
  194. assertEquals(-1, tree.indexOf('pippin'));
  195. assertEquals(-1, tree.indexOf('frodo'));
  196. }
  197. /**
  198. * This test verifies that we can insert values into and remove values from
  199. * the AvlTree and have its minValue and maxValue routines return the correct
  200. * min and max values contained by the tree.
  201. */
  202. function testMinAndMaxValues() {
  203. var tree = new goog.structs.AvlTree(function(a, b) { return a - b; });
  204. var NUM_TO_INSERT = 2000;
  205. var NUM_TO_REMOVE = 500;
  206. // Insert ints into tree out of order
  207. for (var i = 0; i < NUM_TO_INSERT; i += 1) {
  208. tree.add(i);
  209. }
  210. // Remove valuse
  211. for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
  212. tree.remove(i);
  213. }
  214. assertEquals(tree.getMinimum(), NUM_TO_REMOVE);
  215. assertEquals(tree.getMaximum(), NUM_TO_INSERT - 1);
  216. }
  217. /**
  218. * This test verifies that we can insert values into and remove values from
  219. * the AvlTree and traverse the tree in reverse order using the
  220. * reverseOrderTraverse routine.
  221. */
  222. function testReverseOrderTraverse() {
  223. var tree = new goog.structs.AvlTree(function(a, b) { return a - b; });
  224. var NUM_TO_INSERT = 2000;
  225. var NUM_TO_REMOVE = 500;
  226. // Insert ints into tree out of order
  227. for (var i = 0; i < NUM_TO_INSERT; i += 1) {
  228. tree.add(i);
  229. }
  230. // Remove valuse
  231. for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
  232. tree.remove(i);
  233. }
  234. var i = NUM_TO_INSERT - 1;
  235. tree.reverseOrderTraverse(function(value) {
  236. assertEquals(value, i);
  237. i -= 1;
  238. });
  239. assertEquals(i, NUM_TO_REMOVE - 1);
  240. }
  241. /**
  242. * Verifies correct behavior of getCount(). See http://b/4347755
  243. */
  244. function testGetCountBehavior() {
  245. var tree = new goog.structs.AvlTree();
  246. tree.add(1);
  247. tree.remove(1);
  248. assertEquals(0, tree.getCount());
  249. var values = ['bill', 'blake', 'elliot', 'jacob', 'john', 'myles', 'ted'];
  250. // Insert strings into tree out of order
  251. tree.add('frodo');
  252. tree.add(values[4]);
  253. tree.add(values[3]);
  254. tree.add(values[0]);
  255. tree.add(values[6]);
  256. tree.add('samwise');
  257. tree.add(values[5]);
  258. tree.add(values[1]);
  259. tree.add(values[2]);
  260. tree.add('pippin');
  261. assertEquals(10, tree.getCount());
  262. assertEquals(
  263. tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
  264. // Remove strings from tree
  265. assertEquals('samwise', tree.remove('samwise'));
  266. assertEquals('pippin', tree.remove('pippin'));
  267. assertEquals('frodo', tree.remove('frodo'));
  268. assertEquals(null, tree.remove('merry'));
  269. assertEquals(7, tree.getCount());
  270. assertEquals(
  271. tree.root_.left.count + tree.root_.right.count + 1, tree.getCount());
  272. }
  273. /**
  274. * This test verifies that getKthOrder gets the correct value.
  275. */
  276. function testGetKthOrder() {
  277. var tree = new goog.structs.AvlTree(function(a, b) { return a - b; });
  278. var NUM_TO_INSERT = 2000;
  279. var NUM_TO_REMOVE = 500;
  280. // Insert ints into tree out of order
  281. for (var i = 0; i < NUM_TO_INSERT; i += 1) {
  282. tree.add(i);
  283. }
  284. // Remove values.
  285. for (var i = 0; i < NUM_TO_REMOVE; i += 1) {
  286. tree.remove(i);
  287. }
  288. for (var k = 0; k < tree.getCount(); ++k) {
  289. assertEquals(NUM_TO_REMOVE + k, tree.getKthValue(k));
  290. }
  291. }