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