ouija_bh

Scapegoat tree with better performance

Aug 14th, 2025 (edited)
136
0
Never
1
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
JavaScript 21.42 KB | Source Code | 0 0
  1. /* An implementation of scapegoat tree. It has tree methods add, remove,
  2.  * findLE, findEQ, findGE, toArray, size, and clear. Ported from Open
  3.  * Data Structures by Pat Morin. Includes a short demonstration of those
  4.  * methods showing traversals of modified tree.
  5.  * This version has better performing tree methods add and remove by way
  6.  * of Morin Exercise 8..6.
  7.  */
  8.  
  9. /** A node. */
  10. class Vertex {
  11.   /** constructor() credit: Morin 6.1. */
  12.   constructor() {
  13.     this.value;  // any
  14.     this.left;   // Vertex ref
  15.     this.right;  // Vertex ref
  16.     this.parent; // Vertex ref
  17.     this.numV;   // number of vertices in this subtree
  18.     this.bSeen;  // boolean
  19.   }
  20. }
  21.  
  22. /** A sorted set. */
  23. class ScapegoatTree {
  24.   #nil; #root; #compare; #oeNV;
  25.   /** constructor() credit: Morin BinaryTree.java, BinarySearchTree.java, ScapegoatTree.java.
  26.    * @param {function} comparator function taking (any, any) and returning -1, 0, or 1
  27.    */
  28.   constructor(comparator) {
  29.     this.#nil = new Vertex();  // vertex used as null
  30.     this.#nil.numV = 0;
  31.     this.#root = this.#nil;  // root vertex
  32.     this.#compare = comparator;
  33.     this.#oeNV = 0;  // an overestimate of this.#root.numV
  34.   }
  35.  
  36.   /** #newVertex() credit: Morin BinaryTree.java, BinarySearchTree.java.
  37.    * @param {any} value value used to order the tree
  38.    * @returns {Vertex} a new vertex
  39.    */
  40.   #newVertex(value) {
  41.     var vertex = new Vertex();
  42.     vertex.value = value;
  43.     vertex.left = this.#nil;
  44.     vertex.right = this.#nil;
  45.     vertex.parent = this.#nil;
  46.     vertex.bSeen = false;
  47.     return vertex;
  48.   }
  49.  
  50.   /** #buildBalanced() A recursive helper that builds a perfectly balanced
  51.    *  subtree out of array[i], ..., array[i + vxSz - 1]. credit: Morin 8.
  52.    * @param {Array} array array of Vertex's
  53.    * @param {number} i the index i in array
  54.    * @param {number} vxSz vertex size
  55.    * @returns {Vertex} the root of the newly created subtree
  56.    */
  57.   #buildBalanced(array, i, vxSz) {
  58.     if (vxSz == 0) { return this.#nil; }
  59.     var hfVS = Math.floor(vxSz / 2);
  60.     array[i + hfVS].left = this.#buildBalanced(array, i, hfVS);
  61.     if (array[i + hfVS].left != this.#nil) {
  62.       array[i + hfVS].left.parent = array[i + hfVS];
  63.     }
  64.     array[i + hfVS].right = this.#buildBalanced(array, i + hfVS + 1, vxSz - hfVS - 1);
  65.     if (array[i + hfVS].right != this.#nil) {
  66.       array[i + hfVS].right.parent = array[i + hfVS];
  67.     }
  68.     array[i + hfVS].numV = vxSz;
  69.     return array[i + hfVS];
  70.   }
  71.  
  72.   /** #packIntoArray() A recursive helper that packs the subtree rooted at given
  73.    *  vertex into array[i], ..., array[i + size(vertex) - 1]. credit: Morin 8.
  74.    * @param {Vertex} vertex root of subtree
  75.    * @param {boolean} flag pack vertex if false or value if true
  76.    * @param {Array} array array of Vertex's if !flag or any if flag
  77.    * @param {number} i the index i in array
  78.    * @returns {number} size(vertex)
  79.    */
  80.   #packIntoArray(vertex, flag, array, i) {
  81.     if (vertex == this.#nil) { return i; }
  82.     i = this.#packIntoArray(vertex.left, flag, array, i);
  83.     if (flag) { array[i++] = vertex.value; }
  84.     else { array[i++] = vertex; }
  85.     return this.#packIntoArray(vertex.right, flag, array, i);
  86.   }
  87.  
  88.   /** #sizeOfV() Get vertex size. credit: Morin 6.1.1.
  89.    * @param {Vertex} vertex vertex to calculate size for
  90.    * @returns {number} size of given vertex
  91.    */
  92.   #sizeOfV(vertex) {
  93.     if (vertex == this.#nil) { return 0; }
  94.     return 1 + this.#sizeOfV(vertex.left) + this.#sizeOfV(vertex.right);
  95.   }
  96.  
  97.   /** #rebuild() credit: Morin 8.
  98.    * @param {Vertex} vertex root of subtree
  99.    */
  100.   #rebuild(vertex) {
  101.     var p = vertex.parent;
  102.     var array = new Array(vertex.numV);  // of Vertex's
  103.     this.#packIntoArray(vertex, false, array, 0);
  104.     if (p == this.#nil) {
  105.       this.#root = this.#buildBalanced(array, 0, vertex.numV);
  106.       this.#root.parent = this.#nil;
  107.     } else if (p.right == vertex) {
  108.       p.right = this.#buildBalanced(array, 0, vertex.numV);
  109.       p.right.parent = p;
  110.     } else {
  111.       p.left = this.#buildBalanced(array, 0, vertex.numV);
  112.       p.left.parent = p;
  113.     }
  114.   }
  115.  
  116.   /** toArray()
  117.    * @returns {Array} array of in-order values
  118.    */
  119.   toArray() {
  120.     var array = new Array(this.#root.numV);  // of any
  121.     this.#packIntoArray(this.#root, true, array, 0);
  122.     return array;
  123.   }
  124.  
  125.   /** toString()
  126.    * @returns {string} in-order values formatted as array
  127.    */
  128.   toString() {
  129.     return JSON.stringify(this.toArray());
  130.   }
  131.  
  132.   /** #addWithDepth() Do a normal BinarySearchTree insertion, but return the
  133.    *  depth of the newly inserted vertex. credit: Morin ScapegoatTree.java.
  134.    * @param {Vertex} vertex vertex to add
  135.    * @returns {number} the depth of the newly inserted vertex, or -1 if
  136.    *              the vertex was not inserted
  137.    */
  138.   #addWithDepth(vertex) {
  139.     var cur = this.#root;
  140.     if (cur == this.#nil) {
  141.       this.#root = vertex;
  142.       this.#oeNV++;
  143.       return 0;
  144.     }
  145.     var done = false;
  146.     var depth = 0;
  147.     do {
  148.       var res = this.#compare(vertex.value, cur.value);
  149.       if (res < 0) {
  150.         if (cur.left == this.#nil) {
  151.           cur.left = vertex;
  152.           vertex.parent = cur;
  153.           done = true;
  154.         }
  155.         cur = cur.left;
  156.       } else if (res > 0) {
  157.         if (cur.right == this.#nil) {
  158.           cur.right = vertex;
  159.           vertex.parent = cur;
  160.           done = true;
  161.         }
  162.         cur = cur.right;
  163.       } else {
  164.         return -1;
  165.       }
  166.       depth++;
  167.     } while (!done);
  168.     // traverse up the tree, incrementing num. vertices
  169.     while (cur != this.#root) {
  170.       cur = cur.parent;
  171.       cur.numV++;
  172.     }
  173.     this.#oeNV++;
  174.     return depth;
  175.   }
  176.  
  177.   /** log32() Compute the ceiling of log_{3 / 2}(oeNV). credit: Morin ScapegoatTree.java.
  178.    * @param {number} oeNV overestimate of num. vertices
  179.    * @returns {number} the ceiling of log_{3 / 2}(oeNV)
  180.    */
  181.   static log32(oeNV) {
  182.     const log23 = 2.4663034623764317;
  183.     return Math.ceil(log23 * Math.log(oeNV));
  184.   }
  185.  
  186.   /** add() credit: Morin 8.1.
  187.    * @param {any} value value to add
  188.    * @returns {boolean} success?
  189.    */
  190.   add(value) {
  191.     var vertex = this.#newVertex(value);
  192.     vertex.numV = 1;
  193.     var depth = this.#addWithDepth(vertex); // get depth of inserted vertex
  194.     if (depth > ScapegoatTree.log32(this.#oeNV)) {  // depth exceeded, find scapegoat
  195.       var cur = vertex.parent;
  196.       while (3 * cur.numV <= 2 * cur.parent.numV) {
  197.         cur = cur.parent;
  198.       }
  199.       this.#rebuild(cur.parent);
  200.     }
  201.     return depth >= 0;
  202.   }
  203.  
  204.   /** #splice() credit: Morin 6.2.3.
  205.    * @param {Vertex} vertex vertex to splice
  206.    */
  207.   #splice(vertex) {
  208.     var cur, prev;
  209.     if (vertex.left != this.#nil) {
  210.       cur = vertex.left;
  211.     } else {
  212.       cur = vertex.right;
  213.     }
  214.     if (vertex == this.#root) {
  215.       if (cur == vertex.left && vertex.right != this.#nil) {
  216.         cur.numV += vertex.right.numV;
  217.       }
  218.       this.#root = cur;
  219.       prev = this.#nil;
  220.     } else {
  221.       prev = vertex.parent;
  222.       if (prev.left == vertex) {
  223.         prev.left = cur;
  224.       } else {
  225.         prev.right = cur;
  226.       }
  227.       // traverse up the tree, decrementing num. vertices
  228.       var p = vertex.parent;
  229.       do {
  230.         p.numV--;
  231.         p = p.parent;
  232.       } while (p != this.#nil);
  233.     }
  234.     if (cur != this.#nil) {
  235.       cur.parent = prev;
  236.     }
  237.   }
  238.  
  239.   /** #rmVert() Remove the given vertex from the binary search tree.
  240.    *  credit: Morin 6.2.3.
  241.    * @param {Vertex} vertex vertex to remove
  242.    */
  243.   #rmVert(vertex) {
  244.     if (vertex.left == this.#nil || vertex.right == this.#nil) {
  245.       this.#splice(vertex);
  246.     } else {
  247.       var cur = vertex.right;
  248.       while (cur.left != this.#nil) { cur = cur.left; }
  249.       vertex.value = cur.value;
  250.       this.#splice(cur);
  251.     }
  252.   }
  253.  
  254.   /** #findLast() credit: Morin 6.2.2.
  255.    * @param {any} value value for comparison
  256.    * @returns {Vertex} last vertex found on path for value
  257.    */
  258.   #findLast(value) {
  259.     var cur = this.#root, prev = this.#nil;
  260.     while (cur != this.#nil) {
  261.       prev = cur;
  262.       var res = this.#compare(value, cur.value);
  263.       if (res < 0) { cur = cur.left; }
  264.       else if (res > 0) { cur = cur.right; }
  265.       else { return cur; }
  266.     }
  267.     return prev;
  268.   }
  269.  
  270.   /** rmVal() credit: Morin BinarySearchTree.java.
  271.    * @param {any} value value to remove
  272.    * @returns {boolean} success?
  273.    */
  274.   #rmVal(value) {
  275.     var vertex = this.#findLast(value);
  276.     if (vertex != this.#nil && this.#compare(value, vertex.value) == 0) {
  277.       this.#rmVert(vertex);
  278.       return true;
  279.     }
  280.     return false;
  281.   }
  282.  
  283.   /** remove() credit: Morin 8.1.
  284.    * @param {any} value value to remove
  285.    * @returns {boolean} success?
  286.    */
  287.   remove(value) {
  288.     if (this.#rmVal(value)) {
  289.       if (2 * this.#root.numV < this.#oeNV) {
  290.         this.#rebuild(this.#root);
  291.         this.#oeNV = this.#root.numV;
  292.       }
  293.       return true;
  294.     }
  295.     return false;
  296.   }
  297.  
  298.   /** findEQ() Find an equal value. credit: Morin 6.2.1.
  299.    * @param {any} value value to find
  300.    * @returns {any} value if found, undefined if not found
  301.    */
  302.   findEQ(value) {
  303.     var cur = this.#root;
  304.     while (cur != this.#nil) {
  305.       var res = this.#compare(value, cur.value);
  306.       if (res < 0) { cur = cur.left; }
  307.       else if (res > 0) { cur = cur.right; }
  308.       else { return cur.value; }
  309.     }
  310.     return undefined;
  311.   }
  312.  
  313.   /** #findGEVertex() credit: Morin BinarySearchTree.java.
  314.    * @param {any} value value to find
  315.    * @returns {Vertex} last vertex found on path for value
  316.    */
  317.   #findGEVertex(value) {
  318.     var cur = this.#root, last = this.#nil;
  319.     while (cur != this.#nil) {
  320.       var res = this.#compare(value, cur.value);
  321.       if (res < 0) {
  322.         last = cur;
  323.         cur = cur.left;
  324.       } else if (res > 0) {
  325.         cur = cur.right;
  326.       } else {
  327.         return cur;
  328.       }
  329.     }
  330.     return last;
  331.   }
  332.  
  333.   /** findGE() Find smallest value in tree greater than or equal to given value, or undefined
  334.    * if no such value. Or, if given value is undefined then the smallest value in tree.
  335.    * credit: Morin BinarySearchTree.java, SSet.java.
  336.    * @param {any} value value to find
  337.    * @returns {any} smallest value in tree greater than or equal to given value, or undefined if no
  338.    *               such value. Or, if given value is undefined then the smallest value in tree.
  339.    */
  340.   findGE(value) {
  341.     if (value == undefined) {  // find the minimum value
  342.       var cur = this.#root;
  343.       if (cur == this.#nil) { return undefined; }
  344.       while (cur.left != this.#nil) {
  345.         cur = cur.left;
  346.       }
  347.       return cur.value;
  348.     }
  349.     var cur = this.#findGEVertex(value);
  350.     if (cur == this.#nil) { return undefined; }
  351.     return cur.value;
  352.   }
  353.  
  354.   /** #findLEVertex() credit: Morin BinarySearchTree.java.
  355.    * @param {any} value value to find
  356.    * @returns {Vertex} last vertex found on path for value
  357.    */
  358.   #findLEVertex(value) {
  359.     var cur = this.#root, last = this.#nil;
  360.     while (cur != this.#nil) {
  361.       var res = this.#compare(value, cur.value);
  362.       if (res < 0) {
  363.         cur = cur.left;
  364.       } else if (res > 0) {
  365.         last = cur;
  366.         cur = cur.right;
  367.       } else {
  368.         return cur;
  369.       }
  370.     }
  371.     return last;
  372.   }
  373.  
  374.   /** findLE() Find largest value in tree less than or equal to given value, or undefined
  375.    * if no such value. Or, if given value is undefined then the largest value in tree.
  376.    * credit: Morin BinarySearchTree.java findLT [sic].
  377.    * @param {any} value value to find
  378.    * @returns {any} largest value in tree less than or equal to given value, or undefined if no
  379.    *               such value. Or, if given value is undefined then the largest value in tree.
  380.    */
  381.   findLE(value) {
  382.     if (value == undefined) {  // find the maximum value
  383.       var cur = this.#root;
  384.       if (cur == this.#nil) { return undefined; }
  385.       while (cur.right != this.#nil) {
  386.         cur = cur.right;
  387.       }
  388.       return cur.value;
  389.     }
  390.     var cur = this.#findLEVertex(value);
  391.     if (cur == this.#nil) { return undefined; }
  392.     return cur.value;
  393.   }
  394.  
  395.   /** #depth() Get vertex depth. credit: Morin 6.1.
  396.    * @param {Vertex} vertex vertex to calculate depth for
  397.    * @returns {number} depth of given vertex
  398.    */
  399.   #depth(vertex) {
  400.     var count = 0;
  401.     while (vertex != this.#root) {
  402.       vertex = vertex.parent;
  403.       count++;
  404.     }
  405.     return count;
  406.   }
  407.  
  408.   /** size3() Get tree size.
  409.    * @returns {number} size of tree
  410.    */
  411.   size3() {
  412.     return this.#sizeOfV(this.#root);
  413.   }
  414.  
  415.   verify() {
  416.     if (this.size3() != this.#root.numV) {
  417.       throw new Error("verify: size is incorrect");
  418.     } else if (2 * this.#root.numV < this.#oeNV) {
  419.       throw new Error("verify: overestimate is too high");
  420.     } else if (this.height() > ScapegoatTree.log32(this.#oeNV)) {
  421.       throw new Error("verify: tree is too tall");
  422.     }
  423.   }
  424.  
  425.   /** size() Get tree size. credit: Morin BinarySearchTree.java.
  426.    * @returns {number} size of tree
  427.    */
  428.   size() {
  429.     return this.#root.numV;
  430.   }
  431.  
  432.   /** clear() credit: Morin BinaryTree.java, BinarySearchTree.java. */
  433.   clear() {
  434.     this.#root = this.#nil;
  435.   }
  436.  
  437.   /** #heightOfV() Get vertex height. credit: Morin 6.1.1.
  438.    * @param {Vertex} vertex vertex to calculate height for
  439.    * @returns {number} height of given vertex, or -1 if nil vertex
  440.    */
  441.   #heightOfV(vertex) {
  442.     if (vertex == this.#nil) { return -1; }
  443.     return 1 + Math.max(this.#heightOfV(vertex.left), this.#heightOfV(vertex.right));
  444.   }
  445.  
  446.   /** height() Get tree height.
  447.    * @returns {number} height of root, or -1 if nil root
  448.    */
  449.   height() {
  450.     return this.#heightOfV(this.#root);
  451.   }
  452.  
  453.   /** #formatVertices()
  454.    * @param {boolean} flag if true, append additional vertex info
  455.    * @param {Vertex[]} vertices vertices in this tree
  456.    * @returns {string} vertices formatted as tree
  457.    */
  458.   #formatVertices(flag, vertices) {
  459.     var retVertices = "";
  460.     for (var i = 0; i < vertices.length; i++) {
  461.       retVertices += '\n' + " ".repeat(this.#depth(vertices[i]) + 1) + vertices[i].value;
  462.       if (flag) {
  463.         var height = this.#heightOfV(vertices[i]);
  464.         retVertices += "  height=" + height + "  size=" + vertices[i].numV;
  465.         if (vertices[i].parent != this.#nil) {
  466.           retVertices += "  parent=" + vertices[i].parent.value;
  467.         }
  468.       }
  469.     }
  470.     return retVertices;
  471.   }
  472.  
  473.   /** #traverseInner() Inner depth-first traverse. credit: Morin 6.1.2.
  474.    * @param {Vertex} vertex vertex to traverse
  475.    * @param {Vertex[]} dfVertices discovered vertices
  476.    */
  477.   #traverseInner(vertex, dfVertices) {
  478.     if (vertex == this.#nil) { return; }
  479.     vertex.bSeen = true;
  480.     if (!vertex.left.bSeen) {
  481.       vertex.left.bSeen = true;
  482.       this.#traverseInner(vertex.left, dfVertices);
  483.     }
  484.     if (!vertex.right.bSeen) {
  485.       vertex.right.bSeen = true;
  486.       this.#traverseInner(vertex.right, dfVertices);
  487.     }
  488.     dfVertices.unshift(vertex);
  489.   }
  490.  
  491.   /** traverse() Depth-first traverse.
  492.    * @returns {string} vertices formatted as tree
  493.    */
  494.   traverse() {
  495.     var dfVertices = [];
  496.     this.#traverseInner(this.#root, dfVertices);
  497.     this.bfTraverse(false);
  498.     return "depth-first traverse" + this.#formatVertices(false, dfVertices);
  499.   }
  500.  
  501.   /** traverse2() Depth-first traverse. credit: Morin 6.1.2.
  502.    * @returns {string} vertices formatted as tree
  503.    */
  504.   traverse2() {
  505.     var dfVertices = [];
  506.     var cur = this.#root, prev = this.#nil, next;
  507.     while (cur != this.#nil) {
  508.       if (prev == cur.parent) {
  509.         if (cur.left != this.#nil) { next = cur.left; }
  510.         else if (cur.right != this.#nil) { next = cur.right; }
  511.         else { next = cur.parent; }
  512.       } else if (prev == cur.left) {
  513.         if (cur.right != this.#nil) { next = cur.right; }
  514.         else { next = cur.parent; }
  515.       } else {
  516.         next = cur.parent;
  517.       }
  518.       prev = cur;
  519.       if (!cur.bSeen) {
  520.         dfVertices.push(cur);
  521.         cur.bSeen = true;
  522.       }
  523.       cur = next;
  524.     }
  525.     this.bfTraverse(false);
  526.     return "depth-first traverse #2" + this.#formatVertices(false, dfVertices);
  527.   }
  528.  
  529.   /** bfTraverse() Breadth-first traverse. credit: Morin 6.1.2.
  530.    * @param {boolean} flag true: set bSeen, false: unset bSeen
  531.    * @returns {string} vertices formatted as tree
  532.    */
  533.   bfTraverse(flag) {
  534.     var bfVertices = [];
  535.     var queue = [];  // queue of Vertex's
  536.     if (this.#root != this.#nil) {
  537.       queue.push(this.#root);
  538.       this.#root.bSeen = flag;
  539.     }
  540.     while (queue.length > 0) {
  541.       var vertex = queue.shift();
  542.       if (flag) { bfVertices.push(vertex); }
  543.       if (vertex.left != this.#nil) {
  544.         if (flag) {
  545.           if (!vertex.left.bSeen) {
  546.             queue.push(vertex.left);
  547.             vertex.left.bSeen = flag;
  548.           }
  549.         } else {
  550.           queue.push(vertex.left);
  551.           vertex.left.bSeen = flag;
  552.         }
  553.       }
  554.       if (vertex.right != this.#nil) {
  555.         if (flag) {
  556.           if (!vertex.right.bSeen) {
  557.             queue.push(vertex.right);
  558.             vertex.right.bSeen = flag;
  559.           }
  560.         } else {
  561.           queue.push(vertex.right);
  562.           vertex.right.bSeen = flag;
  563.         }
  564.       }
  565.     }
  566.     if (flag) { this.bfTraverse(false); }
  567.     return "breadth-first traverse" + this.#formatVertices(true, bfVertices);
  568.   }
  569.  
  570.   /** size2() Get tree size. credit: Morin 6.1.2.
  571.    * @returns {number} size of tree
  572.    */
  573.   size2() {
  574.     var cur = this.#root, prev = this.#nil, next;
  575.     var count = 0;
  576.     while (cur != this.#nil) {
  577.       if (prev == cur.parent) {
  578.         count++;
  579.         if (cur.left != this.#nil) { next = cur.left; }
  580.         else if (cur.right != this.#nil) { next = cur.right; }
  581.         else { next = cur.parent; }
  582.       } else if (prev == cur.left) {
  583.         if (cur.right != this.#nil) { next = cur.right; }
  584.         else { next = cur.parent; }
  585.       } else {
  586.         next = cur.parent;
  587.       }
  588.       prev = cur;
  589.       cur = next;
  590.     }
  591.     return count;
  592.   }
  593. }
  594.  
  595. /** compare() Compare values. This will work for string and number types.
  596.  * @param {any} a a value
  597.  * @param {any} b another value
  598.  * @returns {number} -1 if a < b, 0 if a == b, 1 if a > b
  599.  */
  600. function compare(a, b) {
  601.   if (a < b) { return -1; }
  602.   else if (a > b) { return 1; }
  603.   return 0;
  604. }
  605.  
  606. /** assertSets() Assert that sizes and values of tree and set are equal.
  607.  * @param {ScapegoatTree} aTree a tree
  608.  * @param {Set} aSet a set
  609.  */
  610. function assertSets(aTree, aSet) {
  611.   if (aTree.size() == aSet.size) {
  612.     var arrVals = aTree.toArray(), setVals = Array.from(aSet).sort(compare);
  613.     for (var i = 0; i < arrVals.length; i++) {
  614.       if (compare(arrVals[i], setVals[i]) != 0) {
  615.         throw new Error("assert: value mismatch");
  616.       }
  617.     }
  618.   } else {
  619.     throw new Error("assert: size mismatch");
  620.   }
  621. }
  622.  
  623.  
  624. var natoValues = ["alpha", "bravo", "charlie", "delta", "echo", "foxtrot", "golf", "hotel",
  625.                   "india", "juliet", "kilo", "lima", "mike", "november", "oscar", "papa",
  626.                   "quebec", "romeo", "sierra", "tango", "uniform"];
  627. var wuValues = ["adams", "boston", "chicago", "denver", "easy", "frank", "george", "henry",
  628.                 "ida", "john", "king", "lincoln", "mary", "new york", "ocean", "peter",
  629.                 "queen", "roger", "sugar", "thomas", "union"];
  630. var sgTree = new ScapegoatTree(compare);
  631. var valuesSet = new Set();
  632. var midNV = Math.floor(natoValues.length / 2);
  633.  
  634. for (var i = 0; i < natoValues.length; i++) {
  635.   sgTree.add(natoValues[i]);
  636.   valuesSet.add(natoValues[i]);
  637. }
  638. console.log("--added " + natoValues.length + " nato phonetics--");
  639. sgTree.verify();
  640. assertSets(sgTree, valuesSet);
  641.  
  642. console.log(sgTree.traverse());
  643.  
  644. console.log("findEQ(" + JSON.stringify(wuValues[0]) + ") = " + sgTree.findEQ(wuValues[0]));
  645. console.log("findGE(" + JSON.stringify(wuValues[0]) + ") = " + sgTree.findGE(wuValues[0]));
  646. console.log("findEQ(" + JSON.stringify(natoValues[0]) + ") = " + sgTree.findEQ(natoValues[0]));
  647. console.log("size = " + sgTree.size());
  648.  
  649. for (var i = wuValues.length - 1; i >= 0; i--) {
  650.   sgTree.add(wuValues[i]);
  651.   valuesSet.add(wuValues[i]);
  652. }
  653. console.log("--added (in reverse order) " + wuValues.length + " western union phonetics--");
  654. sgTree.verify();
  655. assertSets(sgTree, valuesSet);
  656.  
  657. console.log(sgTree.traverse());
  658.  
  659. console.log("findEQ(" + JSON.stringify(wuValues[0]) + ") = " + sgTree.findEQ(wuValues[0]));
  660. console.log("findLE(" + JSON.stringify(natoValues[0]) + ") = " + sgTree.findLE(natoValues[0]));
  661. console.log("minimum = " + sgTree.findGE(undefined) + ", maximum = " + sgTree.findLE(undefined));
  662. console.log("size = " + sgTree.size() + ", size #2 = " + sgTree.size2() + ", size #3 = " + sgTree.size3());
  663. console.log("height = " + sgTree.height());
  664.  
  665. for (var i = 0; i < midNV; i++) {
  666.   sgTree.remove(natoValues[i]);
  667.   valuesSet.delete(natoValues[i]);
  668. }
  669. console.log("--removed first " + midNV + " nato phonetics--");
  670. sgTree.verify();
  671. assertSets(sgTree, valuesSet);
  672.  
  673. console.log(sgTree.traverse2());
  674.  
  675. console.log("findEQ(" + JSON.stringify(natoValues[0]) + ") = " + sgTree.findEQ(natoValues[0]));
  676. console.log("findLE(" + JSON.stringify(natoValues[midNV]) + ") = " + sgTree.findLE(natoValues[midNV]));
  677. console.log("findGE(" + JSON.stringify(natoValues[0]) + ") = " + sgTree.findGE(natoValues[0]));
  678.  
  679. console.log(sgTree.bfTraverse(true));
  680.  
  681. console.log("toString = " + sgTree.toString());
  682. sgTree.clear();
  683. valuesSet.clear();
  684. console.log("--clear--");
  685. console.log("toString = " + sgTree.toString());
  686.  
  687. /** @version 1.0c */
Advertisement
Comments
  • ouija_bh
    84 days
    1. // Append this to the above for a more strenuous test of ScapegoatTree
    2. for (var i = 0; i < 1500; i++) {
    3.   sgTree.add(i);
    4.   valuesSet.add(i);
    5. }
    6. console.log("--added 1500 num--");
    7. sgTree.verify();
    8. assertSets(sgTree, valuesSet);
    9. for (var i = 1249; i >= 250; i--) {
    10.   sgTree.remove(i);
    11.   valuesSet.delete(i);
    12. }
    13. console.log("--removed 1000 num--");
    14. sgTree.verify();
    15. assertSets(sgTree, valuesSet);
    16. for (var i = 1499; i >= 0; i--) {
    17.   sgTree.add(i);
    18.   valuesSet.add(i);
    19. }
    20. console.log("--added 1500 num--");
    21. console.log("sgTree size = " + sgTree.size() + ", set size = " + valuesSet.size);
    22. console.log("height = " + sgTree.height());
    23. sgTree.verify();
    24. assertSets(sgTree, valuesSet);
    25. console.log(sgTree.toString());
Add Comment
Please, Sign In to add comment