You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

479 lines
12 KiB

4 years ago
  1. "use strict"
  2. var makeTree = require("../rbtree.js")
  3. var tape = require("tape")
  4. var util = require("util")
  5. var iota = require("iota-array")
  6. var COLORS = [ "r", "b", "bb" ]
  7. function printTree(tree) {
  8. if(!tree) {
  9. return []
  10. }
  11. return [ COLORS[tree._color], tree.key, printTree(tree.left), printTree(tree.right) ]
  12. }
  13. function print(t) {
  14. console.log(util.inspect(printTree(t.root), {depth:12}))
  15. }
  16. //Ensures the red black axioms are satisfied by tree
  17. function checkTree(tree, t) {
  18. if(!tree.root) {
  19. return
  20. }
  21. t.equals(tree.root._color, 1, "root is black")
  22. function checkNode(node) {
  23. if(!node) {
  24. return [1, 0]
  25. }
  26. if(node._color === 0) {
  27. t.assert(!node.left || node.left._color === 1, "children of red node must be black")
  28. t.assert(!node.right || node.right._color === 1, "children of red node must be black")
  29. } else {
  30. t.equals(node._color, 1, "node color must be red or black")
  31. }
  32. if(node.left) {
  33. t.assert(tree._compare(node.left.key, node.key) <= 0, "left tree order invariant")
  34. }
  35. if(node.right) {
  36. t.assert(tree._compare(node.right.key, node.key) >= 0, "right tree order invariant")
  37. }
  38. var cl = checkNode(node.left)
  39. var cr = checkNode(node.right)
  40. t.equals(cl[0], cr[0], "number of black nodes along all paths to root must be constant")
  41. t.equals(cl[1] + cr[1] + 1, node._count, "item count consistency")
  42. return [cl[0] + node._color, cl[1] + cr[1] + 1]
  43. }
  44. var r = checkNode(tree.root)
  45. t.equals(r[1], tree.length, "tree length")
  46. }
  47. tape("insert()", function(t) {
  48. var t1 = makeTree()
  49. var u = t1
  50. var arr = []
  51. for(var i=20; i>=0; --i) {
  52. var x = i
  53. var next = u.insert(x, true)
  54. checkTree(u, t)
  55. checkTree(next, t)
  56. t.equals(u.length, arr.length)
  57. arr.push(x)
  58. u = next
  59. }
  60. for(var i=-20; i<0; ++i) {
  61. var x = i
  62. var next = u.insert(x, true)
  63. checkTree(u, t)
  64. checkTree(next, t)
  65. arr.sort(function(a,b) { return a-b })
  66. var ptr = 0
  67. u.forEach(function(k,v) {
  68. t.equals(k, arr[ptr++])
  69. })
  70. t.equals(ptr, arr.length)
  71. arr.push(x)
  72. u = next
  73. }
  74. var start = u.begin
  75. for(var i=-20, j=0; j<=40; ++i, ++j) {
  76. t.equals(u.at(j).key, i, "checking at()")
  77. t.equals(start.key, i, "checking iter")
  78. t.equals(start.index, j, "checking index")
  79. t.assert(start.valid, "checking valid")
  80. if(j < 40) {
  81. t.assert(start.hasNext, "hasNext()")
  82. } else {
  83. t.assert(!start.hasNext, "eof hasNext()")
  84. }
  85. start.next()
  86. }
  87. t.assert(!start.valid, "invalid eof iterator")
  88. t.assert(!start.hasNext, "hasNext() at eof fail")
  89. t.equals(start.index, 41, "eof index")
  90. t.end()
  91. })
  92. tape("foreach", function(t) {
  93. var u = iota(31).reduce(function(u, k, v) {
  94. return u.insert(k, v)
  95. }, makeTree())
  96. //Check basic foreach
  97. var visit_keys = []
  98. var visit_vals = []
  99. u.forEach(function(k,v) {
  100. visit_keys.push(k)
  101. visit_vals.push(v)
  102. })
  103. t.same(visit_keys, u.keys)
  104. t.same(visit_vals, u.values)
  105. //Check foreach with termination
  106. visit_keys = []
  107. visit_vals = []
  108. t.equals(u.forEach(function(k,v) {
  109. if(k === 5) {
  110. return 1000
  111. }
  112. visit_keys.push(k)
  113. visit_vals.push(v)
  114. }), 1000)
  115. t.same(visit_keys, u.keys.slice(0, 5))
  116. t.same(visit_vals, u.values.slice(0, 5))
  117. //Check half interval foreach
  118. visit_keys = []
  119. visit_vals = []
  120. u.forEach(function(k,v) {
  121. visit_keys.push(k)
  122. visit_vals.push(v)
  123. }, 3)
  124. t.same(visit_keys, u.keys.slice(3))
  125. t.same(visit_vals, u.values.slice(3))
  126. //Check half interval foreach with termination
  127. visit_keys = []
  128. visit_vals = []
  129. t.equals(u.forEach(function(k,v) {
  130. if(k === 12) {
  131. return 1000
  132. }
  133. visit_keys.push(k)
  134. visit_vals.push(v)
  135. }, 3), 1000)
  136. t.same(visit_keys, u.keys.slice(3, 12))
  137. t.same(visit_vals, u.values.slice(3, 12))
  138. //Check interval foreach
  139. visit_keys = []
  140. visit_vals = []
  141. u.forEach(function(k,v) {
  142. visit_keys.push(k)
  143. visit_vals.push(v)
  144. }, 3, 15)
  145. t.same(visit_keys, u.keys.slice(3, 15))
  146. t.same(visit_vals, u.values.slice(3, 15))
  147. //Check interval foreach with termination
  148. visit_keys = []
  149. visit_vals = []
  150. t.equals(u.forEach(function(k,v) {
  151. if(k === 12) {
  152. return 1000
  153. }
  154. visit_keys.push(k)
  155. visit_vals.push(v)
  156. }, 3, 15), 1000)
  157. t.same(visit_keys, u.keys.slice(3, 12))
  158. t.same(visit_vals, u.values.slice(3, 12))
  159. t.end()
  160. })
  161. function compareIterators(a, b, t) {
  162. t.equals(a.tree, b.tree, "iter trees")
  163. t.equals(a.valid, b.valid, "iter validity")
  164. if(!b.valid) {
  165. return
  166. }
  167. t.equals(a.node, b.node, "iter node")
  168. t.equals(a.key, b.key, "iter key")
  169. t.equals(a.value, b.value, "iter value")
  170. t.equals(a.index, b.index, "iter index")
  171. }
  172. tape("iterators", function(t) {
  173. var u = iota(20).reduce(function(u, k, v) {
  174. return u.insert(k, v)
  175. }, makeTree())
  176. //Try walking forward
  177. var iter = u.begin
  178. var c = iter.clone()
  179. t.ok(iter.hasNext, "must have next at beginneing")
  180. t.ok(!iter.hasPrev, "must not have predecessor")
  181. for(var i=0; i<20; ++i) {
  182. var v = u.at(i)
  183. compareIterators(iter, v, t)
  184. t.equals(iter.index, i)
  185. iter.next()
  186. }
  187. t.ok(!iter.valid, "must be eof iterator")
  188. //Check if the clone worked
  189. compareIterators(c, u.begin, t)
  190. //Try walking backward
  191. var iter = u.end
  192. t.ok(!iter.hasNext, "must not have next")
  193. t.ok(iter.hasPrev, "must have predecessor")
  194. for(var i=19; i>=0; --i) {
  195. var v = u.at(i)
  196. compareIterators(iter, v, t)
  197. t.equals(iter.index, i)
  198. iter.prev()
  199. }
  200. t.ok(!iter.valid, "must be eof iterator")
  201. t.end()
  202. })
  203. tape("remove()", function(t) {
  204. var sz = [1, 2, 10, 20, 23, 31, 32, 33]
  205. for(var n=0; n<sz.length; ++n) {
  206. var c = sz[n]
  207. var u = iota(c).reduce(function(u, k, v) {
  208. return u.insert(k, v)
  209. }, makeTree())
  210. for(var i=0; i<c; ++i) {
  211. checkTree(u.remove(i), t)
  212. }
  213. }
  214. t.end()
  215. })
  216. tape("update()", function(t) {
  217. var arr = [0, 1, 2, 3, 4, 5, 6 ]
  218. var u = arr.reduce(function(u, k, v) {
  219. return u.insert(k, v)
  220. }, makeTree())
  221. for(var iter=u.begin; iter.hasNext; iter.next()) {
  222. var p = iter.value
  223. var updated = iter.update(1000)
  224. t.equals(iter.value, iter.key, "ensure no mutation")
  225. t.equals(updated.find(iter.key).value, 1000, "ensure update applied")
  226. checkTree(updated, t)
  227. checkTree(u, t)
  228. }
  229. t.end()
  230. })
  231. tape("keys and values", function(t) {
  232. var original_keys = [ "potato", "sock", "foot", "apple", "newspaper", "gameboy" ]
  233. var original_values = [ 42, 10, false, "!!!", {}, null ]
  234. var u = makeTree()
  235. for(var i=0; i<original_keys.length; ++i) {
  236. u = u.insert(original_keys[i], original_values[i])
  237. }
  238. var zipped = iota(6).map(function(i) {
  239. return [ original_keys[i], original_values[i] ]
  240. })
  241. zipped.sort(function(a,b) {
  242. if(a[0] < b[0]) { return -1 }
  243. if(a[0] > b[0]) { return 1 }
  244. return 0
  245. })
  246. var keys = zipped.map(function(v) { return v[0] })
  247. var values = zipped.map(function(v) { return v[1] })
  248. t.same(u.keys, keys)
  249. t.same(u.values, values)
  250. t.end()
  251. })
  252. tape("searching", function(t) {
  253. var arr = [0, 1, 1, 1, 1, 2, 3, 4, 5, 6, 6 ]
  254. var u = arr.reduce(function(u, k, v) {
  255. return u.insert(k, v)
  256. }, makeTree())
  257. for(var i=0; i<arr.length; ++i) {
  258. if(arr[i] !== arr[i-1] && arr[i] !== arr[i+1]) {
  259. t.equals(u.get(arr[i]), i, "get " + arr[i])
  260. }
  261. }
  262. t.equals(u.get(-1), undefined, "get missing")
  263. t.equals(u.ge(3).index, 6, "ge simple")
  264. t.equals(u.ge(0.9).index, 1, "ge run start")
  265. t.equals(u.ge(1).index, 1, "ge run mid")
  266. t.equals(u.ge(1.1).index, 5, "ge run end")
  267. t.equals(u.ge(0).index, 0, "ge first")
  268. t.equals(u.ge(6).index, 9, "ge last")
  269. t.equals(u.ge(100).valid, false, "ge big")
  270. t.equals(u.ge(-1).index, 0, "ge small")
  271. t.equals(u.gt(3).index, 7, "gt simple")
  272. t.equals(u.gt(0.9).index, 1, "gt run start")
  273. t.equals(u.gt(1).index, 5, "gt run mid")
  274. t.equals(u.gt(1.1).index, 5, "gt run end")
  275. t.equals(u.gt(0).index, 1, "gt first")
  276. t.equals(u.gt(6).valid, false, "gt last")
  277. t.equals(u.gt(100).valid, false, "gt big")
  278. t.equals(u.gt(-1).index, 0, "ge small")
  279. t.equals(u.le(3).index, 6, "le simple")
  280. t.equals(u.le(0.9).index, 0, "le run start")
  281. t.equals(u.le(1).index, 4, "le run mid")
  282. t.equals(u.le(1.1).index, 4, "le run end")
  283. t.equals(u.le(0).index, 0, "le first")
  284. t.equals(u.le(6).index, 10, "le last")
  285. t.equals(u.le(100).index, 10, "le big")
  286. t.equals(u.le(-1).valid, false, "le small")
  287. t.equals(u.lt(3).index, 5, "lt simple")
  288. t.equals(u.lt(0.9).index, 0, "lt run start")
  289. t.equals(u.lt(1).index, 0, "lt run mid")
  290. t.equals(u.lt(1.1).index, 4, "lt run end")
  291. t.equals(u.lt(0).valid, false, "lt first")
  292. t.equals(u.lt(6).index, 8, "lt last")
  293. t.equals(u.lt(100).index, 10, "lt big")
  294. t.equals(u.lt(-1).valid, false, "lt small")
  295. t.equals(u.find(-1).valid, false, "find missing small")
  296. t.equals(u.find(10000).valid, false, "find missing big")
  297. t.equals(u.find(3).index, 6, "find simple")
  298. t.ok(u.find(1).index > 0, "find repeat")
  299. t.ok(u.find(1).index < 5, "find repeat")
  300. for(var i=0; i<arr.length; ++i) {
  301. t.equals(u.find(arr[i]).key, arr[i], "find " + i)
  302. }
  303. for(var i=0; i<arr.length; ++i) {
  304. t.equals(u.at(i).key, arr[i], "at " + i)
  305. }
  306. t.equals(u.at(-1).valid, false, "at missing small")
  307. t.equals(u.at(1000).valid, false, "at missing big")
  308. t.end()
  309. })
  310. tape("slab-sequence", function(t) {
  311. var tree = makeTree()
  312. tree=tree.insert(0, 0)
  313. checkTree(tree, t)
  314. t.same(tree.values, [0])
  315. tree=tree.insert(1, 1)
  316. checkTree(tree, t)
  317. t.same(tree.values, [0,1])
  318. tree=tree.insert(0.5, 2)
  319. checkTree(tree, t)
  320. t.same(tree.values, [0,2,1])
  321. tree=tree.insert(0.25, 3)
  322. checkTree(tree, t)
  323. t.same(tree.values, [0,3,2,1])
  324. tree=tree.remove(0)
  325. checkTree(tree, t)
  326. t.same(tree.values, [3,2,1])
  327. tree=tree.insert(0.375, 4)
  328. checkTree(tree, t)
  329. t.same(tree.values, [3, 4, 2, 1])
  330. tree=tree.remove(1)
  331. checkTree(tree, t)
  332. t.same(tree.values, [3,4,2])
  333. tree=tree.remove(0.5)
  334. checkTree(tree, t)
  335. t.same(tree.values, [3,4])
  336. tree=tree.remove(0.375)
  337. checkTree(tree, t)
  338. t.same(tree.values, [3])
  339. tree=tree.remove(0.25)
  340. checkTree(tree, t)
  341. t.same(tree.values, [])
  342. t.end()
  343. })
  344. tape("slab-sequence-2", function(t) {
  345. var u = makeTree()
  346. u=u.insert( 12 , 22 )
  347. u=u.insert( 11 , 3 )
  348. u=u.insert( 10 , 28 )
  349. u=u.insert( 13 , 16 )
  350. u=u.insert( 9 , 9 )
  351. u=u.insert( 14 , 10 )
  352. u=u.insert( 8 , 15 )
  353. u=u.insert( 15 , 29 )
  354. u=u.insert( 16 , 4 )
  355. u=u.insert( 7 , 21 )
  356. u=u.insert( 17 , 23 )
  357. u=u.insert( 6 , 2 )
  358. u=u.insert( 5 , 27 )
  359. u=u.insert( 18 , 17 )
  360. u=u.insert( 4 , 8 )
  361. u=u.insert( 31 , 11 )
  362. u=u.insert( 30 , 30 )
  363. u=u.insert( 29 , 5 )
  364. u=u.insert( 28 , 24 )
  365. u=u.insert( 27 , 18 )
  366. u=u.insert( 26 , 12 )
  367. u=u.insert( 25 , 31 )
  368. u=u.insert( 24 , 6 )
  369. u=u.insert( 23 , 25 )
  370. u=u.insert( 19 , 7 )
  371. u=u.insert( 20 , 13 )
  372. u=u.insert( 1 , 20 )
  373. u=u.insert( 0 , 14 )
  374. u=u.insert( 22 , 0 )
  375. u=u.insert( 2 , 1 )
  376. u=u.insert( 3 , 26 )
  377. u=u.insert( 21 , 19 )
  378. u=u.remove( 18 , 17 )
  379. u=u.remove( 17 , 23 )
  380. u=u.remove( 16 , 4 )
  381. u=u.remove( 15 , 29 )
  382. u=u.remove( 14 , 10 )
  383. u=u.remove( 13 , 16 )
  384. u=u.remove( 12 , 22 )
  385. u=u.remove( 6 , 2 )
  386. u=u.remove( 7 , 21 )
  387. u=u.remove( 8 , 15 )
  388. u=u.remove( 11 , 3 )
  389. u=u.remove( 4 , 8 )
  390. u=u.remove( 9 , 9 )
  391. u=u.remove( 10 , 28 )
  392. u=u.remove( 5 , 27 )
  393. u=u.remove( 31 , 11 )
  394. u=u.remove( 0 , 14 )
  395. u=u.remove( 30 , 30 )
  396. u=u.remove( 29 , 5 )
  397. u=u.remove( 1 , 20 )
  398. u=u.remove( 28 , 24 )
  399. u=u.remove( 2 , 1 )
  400. u=u.remove( 3 , 26 )
  401. u=u.remove( 27 , 18 )
  402. u=u.remove( 19 , 7 )
  403. u=u.remove( 26 , 12 )
  404. u=u.remove( 20 , 13 )
  405. u=u.remove( 25 , 31 )
  406. u=u.remove( 24 , 6 )
  407. u=u.remove( 21 , 19 )
  408. u=u.remove( 23 , 25 )
  409. u=u.remove( 22 , 0 )
  410. t.end()
  411. })