32
32
*@module data-structures/size-balanced-tree
33
33
*/
34
34
35
- function CreateSBTreeClass ( Node , Nil ) {
36
- function updateChild ( node , newChild ) {
37
- var parent = node . parent ;
38
- if ( parent !== Nil ) {
39
- if ( parent . right === node ) {
40
- parent . right = newChild ;
41
- } else {
42
- parent . left = newChild ;
43
- }
44
- parent . updateSize ( ) ;
45
- }
46
- if ( newChild !== Nil ) {
47
- newChild . parent = parent ;
48
- }
49
- }
50
-
35
+ function CreateSBTreeClass ( Node , Nil , updateChild ) {
51
36
function LeftRotate ( node , childNode ) {
52
37
/*
53
38
Before rotate:
@@ -69,9 +54,8 @@ function CreateSBTreeClass (Node, Nil) {
69
54
node . right . parent = node ;
70
55
}
71
56
childNode . left = node ;
72
- updateChild ( node , childNode ) ; //Access node.parent
73
- node . parent = childNode ;
74
- node . updateSize ( ) ;
57
+ // setting childNode's parent to node's parent
58
+ updateChild ( node , childNode ) ;
75
59
return childNode ;
76
60
}
77
61
@@ -96,9 +80,8 @@ function CreateSBTreeClass (Node, Nil) {
96
80
node . left . parent = node ;
97
81
}
98
82
childNode . right = node ;
99
- updateChild ( node , childNode ) ; //Access node.parent
100
- node . parent = childNode ;
101
- node . updateSize ( ) ;
83
+ // setting childNode's parent to node's parent
84
+ updateChild ( node , childNode ) ;
102
85
return childNode ;
103
86
}
104
87
@@ -122,7 +105,6 @@ function CreateSBTreeClass (Node, Nil) {
122
105
node = LeftRotate ( node , node . right ) ;
123
106
}
124
107
}
125
- node . updateSize ( ) ;
126
108
if ( node === savedNode ) {
127
109
return node ;
128
110
}
@@ -146,20 +128,6 @@ function CreateSBTreeClass (Node, Nil) {
146
128
return node ;
147
129
}
148
130
149
- function findRightMost ( node ) {
150
- while ( node . right !== Nil ) {
151
- node = node . right ;
152
- }
153
- return node ;
154
- }
155
-
156
- function findLeftMost ( node ) {
157
- while ( node . left !== Nil ) {
158
- node = node . left ;
159
- }
160
- return node ;
161
- }
162
-
163
131
function findNodeAtPos ( node , pos ) {
164
132
while ( pos !== node . left . size ) {
165
133
if ( pos < node . left . size ) {
@@ -183,7 +151,6 @@ function CreateSBTreeClass (Node, Nil) {
183
151
184
152
SBTree . prototype = {
185
153
_root :Nil ,
186
- updateChild :updateChild ,
187
154
get size ( ) {
188
155
return this . _root . size ;
189
156
} ,
@@ -208,26 +175,8 @@ function CreateSBTreeClass (Node, Nil) {
208
175
} ,
209
176
} ;
210
177
211
- /**
212
- * Push a value to the end of tree.
213
- * Complexity: O(log N).
214
- *
215
- *@public
216
- *@method
217
- *@param {Object } value Value.
218
- */
219
- SBTree . prototype . push = function ( value ) {
220
- var node = findRightMost ( this . _root ) ;
221
- var newNode = new Node ( value , node , Nil , Nil , 1 ) ;
222
- if ( node !== Nil ) {
223
- node . right = newNode ;
224
- }
225
- this . _root = maintainSizeBalancedTree ( newNode ) ;
226
- return newNode ;
227
- } ;
228
-
229
178
SBTree . prototype . get = function ( pos ) {
230
- if ( pos >= this . _root . size ) {
179
+ if ( pos >= this . size ) {
231
180
return Nil ;
232
181
}
233
182
return findNodeAtPos ( this . _root , pos ) ;
@@ -245,83 +194,97 @@ function CreateSBTreeClass (Node, Nil) {
245
194
return index ;
246
195
} ;
247
196
248
- SBTree . prototype . insert = function ( pos , value ) {
249
- if ( pos >= this . _root . size ) {
250
- return this . push ( value ) ;
197
+ SBTree . prototype . shiftDown = function ( node ) {
198
+ var direction = 0 ;
199
+ while ( true ) {
200
+ if ( node . left !== Nil && node . right !== Nil ) {
201
+ switch ( direction ) {
202
+ case 0 :
203
+ RightRotate ( node , node . left ) ;
204
+ break ;
205
+ case 1 :
206
+ LeftRotate ( node , node . right ) ;
207
+ break ;
208
+ }
209
+ direction = 1 - direction ;
210
+ } else if ( node . left !== Nil ) {
211
+ RightRotate ( node , node . left ) ;
212
+ } else if ( node . right !== Nil ) {
213
+ LeftRotate ( node , node . right ) ;
214
+ } else {
215
+ break ; // The node could be able to removed
216
+ }
251
217
}
252
- var node = findNodeAtPos ( this . _root , pos ) ;
253
- var newNode ;
254
- if ( node . left === Nil ) {
255
- newNode = new Node ( value , node , Nil , Nil , 1 ) ;
256
- node . left = newNode ;
218
+ } ;
219
+
220
+ SBTree . prototype . insertLeafNode = function ( node ) {
221
+ var parent = node . parent ;
222
+ while ( parent !== Nil ) {
223
+ parent . size = parent . size + 1 ;
224
+ parent = parent . parent ;
225
+ }
226
+ } ;
227
+
228
+ SBTree . prototype . removeLeafNode = function ( node ) {
229
+ var parent = node . parent ;
230
+ while ( parent !== Nil ) {
231
+ parent . size = parent . size - 1 ;
232
+ parent = parent . parent ;
233
+ }
234
+ } ;
235
+
236
+ SBTree . prototype . insert = function ( pos , value ) {
237
+ var node = Nil ;
238
+ var newNode = new Node ( value , Nil , Nil , Nil , 1 ) ;
239
+ if ( pos === this . size ) {
240
+ if ( pos > 0 ) {
241
+ node = findNodeAtPos ( this . _root , pos - 1 ) ;
242
+ node . right = newNode ;
243
+ }
257
244
} else {
258
- node = findRightMost ( node . left ) ;
259
- newNode = new Node ( value , node , Nil , Nil , 1 ) ;
260
- node . right = newNode ;
245
+ node = findNodeAtPos ( this . _root , pos ) ;
246
+ if ( node . left !== Nil ) {
247
+ this . shiftDown ( node ) ;
248
+ }
249
+ node . left = newNode ;
261
250
}
251
+ newNode . parent = node ;
252
+ this . insertLeafNode ( newNode ) ;
262
253
this . _root = maintainSizeBalancedTree ( newNode ) ;
263
254
return newNode ;
264
255
} ;
265
256
257
+ /**
258
+ * Push a value to the end of tree.
259
+ * Complexity: O(log N).
260
+ *
261
+ *@public
262
+ *@method
263
+ *@param {Object } value Value.
264
+ */
265
+ SBTree . prototype . push = function ( value ) {
266
+ this . insert ( this . size , value ) ;
267
+ } ;
268
+
269
+ SBTree . prototype . removeNode = function ( node ) {
270
+ this . shiftDown ( node ) ;
271
+ var maintainNode = node . parent ;
272
+ if ( maintainNode . left === node ) {
273
+ maintainNode . left = Nil ;
274
+ } else if ( maintainNode . right === node ) {
275
+ maintainNode . right = Nil ;
276
+ }
277
+ this . removeLeafNode ( node ) ;
278
+ this . _root = maintainSizeBalancedTree ( maintainNode ) ;
279
+ return node ;
280
+ } ;
281
+
266
282
SBTree . prototype . remove = function ( pos ) {
267
283
if ( pos >= this . _root . size ) {
268
284
return Nil ; // There is no element to remove
269
285
}
270
286
var node = findNodeAtPos ( this . _root , pos ) ;
271
- var maintainNode ;
272
-
273
- /*
274
- Before remove:
275
- P (node's parent, be notices,
276
- | N either be left child or right child of P)
277
- |
278
- N(node)
279
- / \
280
- L R
281
- \
282
- \
283
- LRM(Left-Rightmost)
284
- \
285
- Nil
286
- After remove node N:
287
- P(node's parent)
288
- /
289
- L
290
- \
291
- \
292
- LRM(Left-Rightmost)
293
- \
294
- R
295
-
296
- N(node) is wild node that was removed
297
-
298
- */
299
- if ( node . left !== Nil ) {
300
- var LRM = findRightMost ( node . left ) ;
301
- updateChild ( node , node . left ) ;
302
- LRM . right = node . right ;
303
- if ( LRM . right === Nil ) {
304
- maintainNode = LRM ;
305
- } else {
306
- LRM . right . parent = LRM ;
307
- maintainNode = LRM . right ;
308
- }
309
- } else if ( node . right !== Nil ) {
310
- var RLM = findLeftMost ( node . right ) ;
311
- updateChild ( node , node . right ) ;
312
- RLM . left = node . left ;
313
- if ( RLM . left === Nil ) {
314
- maintainNode = RLM ;
315
- } else {
316
- RLM . left . parent = RLM ;
317
- maintainNode = RLM . left ;
318
- }
319
- } else {
320
- updateChild ( node , Nil ) ;
321
- maintainNode = node . parent ;
322
- }
323
- this . _root = maintainSizeBalancedTree ( maintainNode ) ;
324
- return node ;
287
+ return this . removeNode ( node ) ;
325
288
} ;
326
289
327
290
return SBTree ;
@@ -349,6 +312,14 @@ function CreateSBTreeClass (Node, Nil) {
349
312
this . height = 0 ;
350
313
} ;
351
314
315
+ var createNil = function ( Node , value ) {
316
+ var Nil = new Node ( value , null , null , null , 0 ) ;
317
+ Nil . parent = Nil ;
318
+ Nil . left = Nil ;
319
+ Nil . right = Nil ;
320
+ return Nil ;
321
+ } ;
322
+
352
323
/**
353
324
* Update node's size.
354
325
*
@@ -360,12 +331,22 @@ function CreateSBTreeClass (Node, Nil) {
360
331
this . height = Math . max ( this . left . height , this . right . height ) + 1 ;
361
332
} ;
362
333
363
- var createNil = function ( Node , value ) {
364
- var Nil = new Node ( value , null , null , null , 0 ) ;
365
- Nil . parent = Nil ;
366
- Nil . left = Nil ;
367
- Nil . right = Nil ;
368
- return Nil ;
334
+ // node, childNode must not be Nil,
335
+ // if the childNode turn out to be the root, the parent should be Nil
336
+ var updateChild = function ( node , childNode ) {
337
+ var parent = node . parent ;
338
+ node . parent = childNode ;
339
+ childNode . parent = parent ;
340
+
341
+ node . updateSize ( ) ;
342
+ childNode . updateSize ( ) ;
343
+ if ( parent . right === node ) {
344
+ parent . right = childNode ;
345
+ parent . updateSize ( ) ;
346
+ } else if ( parent . left === node ) {
347
+ parent . left = childNode ;
348
+ parent . updateSize ( ) ;
349
+ } // otherwise parent is Nil
369
350
} ;
370
351
371
352
var Node = function ( ) {
@@ -379,11 +360,11 @@ function CreateSBTreeClass (Node, Nil) {
379
360
exports . NodeConstructor = NodeConstructor ;
380
361
exports . createNil = createNil ;
381
362
exports . updateSize = updateSize ;
363
+ exports . updateChild = updateChild ;
382
364
exports . CreateSBTreeClass = CreateSBTreeClass ;
383
365
384
366
exports . Node = Node ;
385
367
exports . Nil = Nil ;
386
- exports . SBTree = CreateSBTreeClass ( Node , Nil ) ;
387
- exports . updateChild = exports . SBTree . prototype . updateChild ;
368
+ exports . SBTree = CreateSBTreeClass ( Node , Nil , updateChild ) ;
388
369
389
370
} ) ( typeof module === 'undefined' ?window :module . exports ) ;