Advertisement
rg443

AVLTree.js

Sep 8th, 2015
256
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. function(window, undefined) {
  2.   var BIND = function(fn, selfObj, arguments) {
  3.     if (!fn) {
  4.       throw new Error;
  5.     }
  6.     if (arguments.length > 2) {
  7.       var boundArgs = Array.prototype.slice.call(arguments, 2);
  8.       return function() {
  9.         var newArgs = Array.prototype.slice.call(arguments);
  10.         Array.prototype.unshift.apply(newArgs, boundArgs);
  11.         return fn.apply(selfObj, newArgs);
  12.       };
  13.     } else {
  14.       return function() {
  15.         return fn.apply(selfObj, arguments);
  16.       };
  17.     }
  18.   };
  19.   AVLTree = function(comparator) {
  20.     this._comparator = comparator || AVLTree.DEFAULT_COMPARATOR;
  21.   };
  22.   AVLTree.DEFAULT_COMPARATOR = function(a, b) {
  23.     if (String(a) < String(b)) {
  24.       return -1;
  25.     } else {
  26.       if (String(a) > String(b)) {
  27.         return 1;
  28.       }
  29.     }
  30.     return 0;
  31.   };
  32.   AVLTree.prototype._root = null;
  33.   AVLTree.prototype._comparator = null;
  34.   AVLTree.prototype._minNode = null;
  35.   AVLTree.prototype._maxNode = null;
  36.   AVLTree.prototype.add = function(value) {
  37.     if (this._root == null) {
  38.       this._root = new AVLTree.Node(value);
  39.       this._minNode = this._root;
  40.       this._maxNode = this._root;
  41.       return true;
  42.     }
  43.     var newNode = null;
  44.     this._traverse(function(node) {
  45.       var retNode = null;
  46.       if (this._comparator(node.value, value) > 0) {
  47.         retNode = node._left;
  48.         if (node._left == null) {
  49.           newNode = new AVLTree.Node(value, node);
  50.           node._left = newNode;
  51.           if (node == this._minNode) {
  52.             this._minNode = newNode;
  53.           }
  54.         }
  55.       } else {
  56.         if (this._comparator(node.value, value) < 0) {
  57.           retNode = node._right;
  58.           if (node._right == null) {
  59.             newNode = new AVLTree.Node(value, node);
  60.             node._right = newNode;
  61.             if (node == this._maxNode) {
  62.               this._maxNode = newNode;
  63.             }
  64.           }
  65.         }
  66.       }
  67.       return retNode;
  68.     });
  69.     if (newNode) {
  70.       this._traverse(function(node) {
  71.         node.count++;
  72.         return node._parent;
  73.       }, newNode._parent);
  74.       this._balance(newNode._parent);
  75.     }
  76.     return !!newNode;
  77.   };
  78.   AVLTree.prototype.remove = function(value) {
  79.     var retValue = null;
  80.     this._traverse(function(node) {
  81.       var retNode = null;
  82.       if (this._comparator(node.value, value) > 0) {
  83.         retNode = node._left;
  84.       } else {
  85.         if (this._comparator(node.value, value) < 0) {
  86.           retNode = node._right;
  87.         } else {
  88.           retValue = node.value;
  89.           this._removeNode(node);
  90.         }
  91.       }
  92.       return retNode;
  93.     });
  94.     return retValue;
  95.   };
  96.   AVLTree.prototype.clear = function() {
  97.     this._root = null;
  98.     this._minNode = null;
  99.     this._maxNode = null;
  100.   };
  101.   AVLTree.prototype.contains = function(value) {
  102.     var isContained = false;
  103.     this._traverse(function(node) {
  104.       var retNode = null;
  105.       if (this._comparator(node.value, value) > 0) {
  106.         retNode = node._left;
  107.       } else {
  108.         if (this._comparator(node.value, value) < 0) {
  109.           retNode = node._right;
  110.         } else {
  111.           isContained = true;
  112.         }
  113.       }
  114.       return retNode;
  115.     });
  116.     return isContained;
  117.   };
  118.   AVLTree.prototype.getCount = function() {
  119.     return this._root ? this._root.count : 0;
  120.   };
  121.   AVLTree.prototype.getNthValue = function(n) {
  122.     if (n < 0 || n >= this.getCount()) {
  123.       return null;
  124.     }
  125.     return this._getNthNode(n).value;
  126.   };
  127.   AVLTree.prototype.getMinimum = function() {
  128.     return this._getMinNode().value;
  129.   };
  130.   AVLTree.prototype.getMaximum = function() {
  131.     return this._getMaxNode().value;
  132.   };
  133.   AVLTree.prototype.getHeight = function() {
  134.     return this._root ? this._root.height : 0;
  135.   };
  136.   AVLTree.prototype.getValues = function() {
  137.     var retVal = [];
  138.     this.inOrderTraverse(function(value) {
  139.       retVal.push(value);
  140.     });
  141.     return retVal;
  142.   };
  143.   AVLTree.prototype.inOrderTraverse = function(func, startValue) {
  144.     if (!this._root) {
  145.       return;
  146.     }
  147.     var startNode;
  148.     if (startValue) {
  149.       this._traverse(function(node) {
  150.         var retNode = null;
  151.         if (this._comparator(node.value, startValue) > 0) {
  152.           retNode = node._left;
  153.           startNode = node;
  154.         } else {
  155.           if (this._comparator(node.value, startValue) < 0) {
  156.             retNode = node._right;
  157.           } else {
  158.             startNode = node;
  159.           }
  160.         }
  161.         return retNode;
  162.       });
  163.     } else {
  164.       startNode = this._getMinNode();
  165.     }
  166.     var node = startNode, previous = startNode._left ? startNode._left : startNode;
  167.     while (node != null) {
  168.       if (node._left != null && node._left != previous && node._right != previous) {
  169.         node = node._left;
  170.       } else {
  171.         if (node._right != previous) {
  172.           if (func(node.value)) {
  173.             return;
  174.           }
  175.         }
  176.         var temp = node;
  177.         node = node._right != null && node._right != previous ? node._right : node._parent;
  178.         previous = temp;
  179.       }
  180.     }
  181.   };
  182.   AVLTree.prototype.reverseOrderTraverse = function(func, startValue) {
  183.     if (!this._root) {
  184.       return;
  185.     }
  186.     var startNode;
  187.     if (startValue) {
  188.       this._traverse(BIND(function(node) {
  189.         var retNode = null;
  190.         if (this._comparator(node.value, startValue) > 0) {
  191.           retNode = node._left;
  192.         } else {
  193.           if (this._comparator(node.value, startValue) < 0) {
  194.             retNode = node._right;
  195.             startNode = node;
  196.           } else {
  197.             startNode = node;
  198.           }
  199.         }
  200.         return retNode;
  201.       }, this));
  202.     } else {
  203.       startNode = this._getMaxNode();
  204.     }
  205.     var node = startNode, prev = startNode._right ? startNode._right : startNode;
  206.     while (node != null) {
  207.       if (node._right != null && node._right != prev && node._left != prev) {
  208.         node = node._right;
  209.       } else {
  210.         if (node._left != prev) {
  211.           if (func(node.value)) {
  212.             return;
  213.           }
  214.         }
  215.         var temp = node;
  216.         node = node._left != null && node._left != prev ? node._left : node._parent;
  217.         prev = temp;
  218.       }
  219.     }
  220.   };
  221.   AVLTree.prototype.printAVLTree = function() {
  222.     if (this._root !== null) {
  223.       return this._root._inOrderPrint();
  224.     }
  225.     return false;
  226.   };
  227.   AVLTree.prototype._traverse = function(traversalFunc, startNode, endNode) {
  228.     var node = startNode ? startNode : this._root;
  229.     var endNode = endNode ? endNode : null;
  230.     while (node && node != endNode) {
  231.       node = traversalFunc.call(this, node);
  232.     }
  233.   };
  234.   AVLTree.prototype._balance = function(node) {
  235.     this._traverse(function(node) {
  236.       var leftHeight = node._left ? node._left.height : 0;
  237.       var rightHeight = node._right ? node._right.height : 0;
  238.       if (leftHeight - rightHeight > 1) {
  239.         if (node._left._right && (!node._left._left || node._left._left.height < node._left._right.height)) {
  240.           this._leftRotate(node._left);
  241.         }
  242.         this._rightRotate(node);
  243.       } else {
  244.         if (rightHeight - leftHeight > 1) {
  245.           if (node._right._left && (!node._right._right || node._right._right.height < node._right._left.height)) {
  246.             this._rightRotate(node._right);
  247.           }
  248.           this._leftRotate(node);
  249.         }
  250.       }
  251.       leftHeight = node._left ? node._left.height : 0;
  252.       rightHeight = node._right ? node._right.height : 0;
  253.       node.height = Math.max(leftHeight, rightHeight) + 1;
  254.       return node._parent;
  255.     }, node);
  256.   };
  257.   AVLTree.prototype._leftRotate = function(node) {
  258.     if (node.isLeftChild()) {
  259.       node._parent._left = node._right;
  260.       node._right._parent = node._parent;
  261.     } else {
  262.       if (node.isRightChild()) {
  263.         node._parent._right = node._right;
  264.         node._right._parent = node._parent;
  265.       } else {
  266.         this._root = node._right;
  267.         this._root._parent = null;
  268.       }
  269.     }
  270.     var temp = node._right;
  271.     node._right = node._right._left;
  272.     if (node._right != null) {
  273.       node._right._parent = node;
  274.     }
  275.     temp._left = node;
  276.     node._parent = temp;
  277.     temp.count = node.count;
  278.     node.count -= (temp._right ? temp._right.count : 0) + 1;
  279.   };
  280.   AVLTree.prototype._rightRotate = function(node) {
  281.     if (node.isLeftChild()) {
  282.       node._parent._left = node._left;
  283.       node._left._parent = node._parent;
  284.     } else {
  285.       if (node.isRightChild()) {
  286.         node._parent._right = node._left;
  287.         node._left._parent = node._parent;
  288.       } else {
  289.         this._root = node._left;
  290.         this._root._parent = null;
  291.       }
  292.     }
  293.     var temp = node._left;
  294.     node._left = node._left._right;
  295.     if (node._left != null) {
  296.       node._left._parent = node;
  297.     }
  298.     temp._right = node;
  299.     node._parent = temp;
  300.     temp.count = node.count;
  301.     node.count -= (temp._left ? temp._left.count : 0) + 1;
  302.   };
  303.   AVLTree.prototype._removeNode = function(node) {
  304.     if (node._left != null || node._right != null) {
  305.       var balanceBegin = null;
  306.       var replacementNode;
  307.       if (node._left != null) {
  308.         r = this._getMaxNode(node._left);
  309.         this._traverse(function(node) {
  310.           node.count--;
  311.           return node._parent;
  312.         }, replacementNode);
  313.         if (replacementNode != node._left) {
  314.           replacementNode._parent._right = replacementNode._left;
  315.           if (replacementNode._left) {
  316.             replacementNode._left._parent = replacementNode._parent;
  317.           }
  318.           replacementNode._left = node._left;
  319.           replacementNode._left._parent = replacementNode;
  320.           balanceBegin = replacementNode._parent;
  321.         }
  322.         replacementNode._parent = node._parent;
  323.         replacementNode._right = node._right;
  324.         if (replacementNode._right) {
  325.           replacementNode._right._parent = replacementNode;
  326.         }
  327.         if (node == this._maxNode) {
  328.           this._maxNode = replacementNode;
  329.         }
  330.         replacementNode.count = node.count;
  331.       } else {
  332.         r = this._getMinNode(node._right);
  333.         this._traverse(function(node) {
  334.           node.count--;
  335.           return node._parent;
  336.         }, replacementNode);
  337.         if (replacementNode != node._right) {
  338.           replacementNode._parent._left = replacementNode._right;
  339.           if (replacementNode._right) {
  340.             replacementNode._right._parent = replacementNode._parent;
  341.           }
  342.           replacementNode._right = node._right;
  343.           replacementNode._right._parent = replacementNode;
  344.           balanceBegin = replacementNode._parent;
  345.         }
  346.         replacementNode._parent = node._parent;
  347.         replacementNode._left = node._left;
  348.         if (replacementNode._left) {
  349.           replacementNode._left._parent = replacementNode;
  350.         }
  351.         if (node == this._minNode) {
  352.           this._minNode = replacementNode;
  353.         }
  354.         replacementNode.count = node.count;
  355.       }
  356.       if (node.isLeftChild()) {
  357.         node._parent._left = replacementNode;
  358.       } else {
  359.         if (node.isRightChild()) {
  360.           node._parent._right = replacementNode;
  361.         } else {
  362.           this._root = replacementNode;
  363.         }
  364.       }
  365.       this._balance(balanceBegin ? balanceBegin : replacementNode);
  366.     } else {
  367.       this._traverse(function(node) {
  368.         node.count--;
  369.         return node._parent;
  370.       }, node._parent);
  371.       if (node.isLeftChild()) {
  372.         this.special = 1;
  373.         node._parent._left = null;
  374.         if (node == this._minNode) {
  375.           this._minNode = node._parent;
  376.         }
  377.         this._balance(node._parent);
  378.       } else {
  379.         if (node.isRightChild()) {
  380.           node._parent._right = null;
  381.           if (node == this._maxNode) {
  382.             this._maxNode = node._parent;
  383.           }
  384.           this._balance(node._parent);
  385.         } else {
  386.           this.clear();
  387.         }
  388.       }
  389.     }
  390.   };
  391.   AVLTree.prototype._getNthNode = function(n, rootNode) {
  392.     var root = rootNode || this._root;
  393.     var numNodesInLeftSubtree = root._left ? root._left.count : 0;
  394.     if (n < numNodesInLeftSubtree) {
  395.       return this._getNthNode(n, root._left);
  396.     } else {
  397.       if (n == numNodesInLeftSubtree) {
  398.         return root;
  399.       } else {
  400.         return this._getNthNode(n - numNodesInLeftSubtree - 1, root._right);
  401.       }
  402.     }
  403.   };
  404.   AVLTree.prototype._getMinNode = function(rootNode) {
  405.     if (!rootNode) {
  406.       return this._minNode;
  407.     }
  408.     var minNode = rootNode;
  409.     this._traverse(function(node) {
  410.       var retNode = null;
  411.       if (node._left) {
  412.         minNode = node._left;
  413.         retNode = node._left;
  414.       }
  415.       return retNode;
  416.     }, rootNode);
  417.     return minNode;
  418.   };
  419.   AVLTree.prototype._getMaxNode = function(rootNode) {
  420.     if (!rootNode) {
  421.       return this._maxNode;
  422.     }
  423.     var maxNode = rootNode;
  424.     this._traverse(function(node) {
  425.       var retNode = null;
  426.       if (node._right) {
  427.         maxNode = node._right;
  428.         retNode = node._right;
  429.       }
  430.       return retNode;
  431.     }, rootNode);
  432.     return maxNode;
  433.   };
  434.   AVLTree.Node = function(value, parent) {
  435.     this.value = value;
  436.     this._parent = parent ? parent : null;
  437.     this.count = 1;
  438.   };
  439.   AVLTree.Node.prototype._inOrderPrint = function(padding) {
  440.     padding = padding || "";
  441.     padding = "--" + padding;
  442.     if (this._left !== null) {
  443.       this._left._inOrderPrint(padding);
  444.     }
  445.     console.log(padding + this.value);
  446.     if (this._right !== null) {
  447.       this._right._inOrderPrint(padding);
  448.     }
  449.   };
  450.   AVLTree.Node.prototype._left = null;
  451.   AVLTree.Node.prototype._right = null;
  452.   AVLTree.Node.prototype.height = 1;
  453.   AVLTree.Node.prototype.isRightChild = function() {
  454.     return !!this._parent && this._parent._right == this;
  455.   };
  456.   AVLTree.Node.prototype.isLeftChild = function() {
  457.     return !!this._parent && this._parent._left == this;
  458.   };
  459.   if (typeof module === "object" && module && typeof module.exports === "object") {
  460.     module.exports = AVLTree;
  461.   } else {
  462.     window.AVLTree = AVLTree;
  463.     if (typeof define === "function" && define.amd) {
  464.       define("avltree", [], function() {
  465.         return AVLTree;
  466.       });
  467.     }
  468.   }
  469. })(window);
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement