1 var define = require("../define").define, 2 Tree = require("./Tree"), 3 base = require("../base"), 4 multiply = base.string.multiply; 5 6 var RED = "red", BLACK = "black"; 7 8 9 var nil = {level : 0, data : null}; 10 11 var makeNode = function(data, level) { 12 return { 13 data : data, 14 level : level, 15 left : nil, 16 right : nil 17 } 18 }; 19 20 var skew = function(root) { 21 if (root.level != 0 && root.left.level == root.level) { 22 var save = root.left; 23 root.left = save.right; 24 save.right = root; 25 root = save; 26 } 27 return root; 28 }; 29 30 var split = function(root) { 31 if (root.level != 0 && root.right.right.level == root.level) { 32 var save = root.right; 33 root.right = save.left; 34 save.left = root; 35 root = save; 36 ++root.level; 37 } 38 return root; 39 }; 40 41 var insert = function(root, data, compare) { 42 if (root == nil) { 43 root = makeNode(data, 1); 44 } 45 else { 46 var dir = compare(data, root.data) == -1 ? "left" : "right"; 47 root[dir] = insert(root[dir], data, compare); 48 root = skew(root); 49 root = split(root); 50 } 51 return root; 52 }; 53 54 var remove = function(root, data, compare) { 55 var rLeft, rRight; 56 if (root != nil) { 57 var cmp = compare(data, root.data); 58 if (cmp == 0) { 59 rLeft = root.left,rRight = root.right; 60 if (rLeft != nil && rRight != nil) { 61 var heir = rLeft; 62 while (heir.right != nil) 63 heir = heir.right; 64 root.data = heir.data; 65 root.left = remove(rLeft, heir.data, compare); 66 } else { 67 root = root[rLeft == nil ? "right" : "left"]; 68 } 69 } else { 70 var dir = cmp == -1 ? "left" : "right"; 71 root[dir] = remove(root[dir], data, compare); 72 } 73 } 74 if (root != nil) { 75 var rLevel = root.level; 76 var rLeftLevel = root.left.level, rRightLevel = root.right.level; 77 if (rLeftLevel < rLevel - 1 || rRightLevel < rLevel - 1) { 78 if (rRightLevel > --root.level) 79 root.right.level = root.level; 80 81 root = skew(root); 82 root = split(root); 83 } 84 } 85 return root; 86 }; 87 /** 88 * @class <p>Andersson Trees are a version of a balanced Binary tree, while similar to RedBlack Trees the balancing is not as strict.</p> 89 * 90 * <b>Performance</b> 91 * <table> 92 * <tr><td></td><td>Best</td><td>Worst</td></tr> 93 * <tr><td>space</td><td>O(n)</td><td>O(n)</td></tr> 94 * <tr><td>Search</td><td>O(log n)</td><td>O(log n)</td></tr> 95 * <tr><td>Insert</td><td>O(log n)</td><td>O(log n)</td></tr> 96 * <tr><td>Delete</td><td>O(log n)</td><td>O(log n)</td></tr> 97 * <table> 98 * @name AnderssonTree 99 * @augments comb.collections.Tree 100 * @memberOf comb.collections 101 */ 102 103 104 module.exports = exports = define(Tree, { 105 106 instance : { 107 /**@lends comb.collections.AnderssonTree.prototype*/ 108 109 isEmpty : function() { 110 return this.__root == nil || this._super(arguments); 111 }, 112 113 insert : function(data) { 114 if (this.__root == null) this.__root = nil; 115 this.__root = insert(this.__root, data, this.compare); 116 }, 117 118 remove : function(data) { 119 this.__root = remove(this.__root, data, this.compare); 120 }, 121 122 123 traverseWithCondition : function(node, order, callback) { 124 var cont = true; 125 if (node != nil) { 126 return this._super(arguments); 127 } 128 return cont; 129 }, 130 131 132 traverse : function(node, order, callback) { 133 if (node != nil) { 134 this._super(arguments); 135 } 136 }, 137 138 contains : function(value) { 139 if (this.__root != nil) { 140 return this._super(arguments); 141 } 142 return false; 143 }, 144 145 __printNode : function(node, level) { 146 var str = []; 147 if (node.data == null || node == null) { 148 str.push(multiply('\t', level)); 149 str.push("~"); 150 console.log(str.join("")); 151 } else { 152 this.__printNode(node.right, level + 1); 153 str.push(multiply('\t', level)); 154 str.push(node.data + ":" + node.level + "\n"); 155 console.log(str.join("")); 156 this.__printNode(node.left, level + 1); 157 } 158 } 159 160 } 161 162 }); 163 164