@@ -64,7 +64,7 @@ AVLTree *avltree_new(AVLTreeCompareFunc compare_func)
64
64
return new_tree ;
65
65
}
66
66
67
- static int avltree_subtree_height (AVLTreeNode * node )
67
+ int avltree_subtree_height (AVLTreeNode * node )
68
68
{
69
69
if (node == <
10000
span class=pl-c1>NULL) {
70
70
return 0 ;
@@ -147,6 +147,14 @@ static void avltree_rotate_left(AVLTree *tree, AVLTreeNode *node)
147
147
node -> right_child = new_root -> left_child ;
148
148
new_root -> left_child = node ;
149
149
150
+ /* Update parent references */
151
+
152
+ node -> parent = new_root ;
153
+
154
+ if (node -> right_child != NULL ) {
155
+ node -> right_child -> parent = node ;
156
+ }
157
+
150
158
/* Update heights of the affected nodes */
151
159
152
160
avltree_update_height (new_root );
@@ -209,20 +217,99 @@ static void avltree_rotate_right(AVLTree *tree, AVLTreeNode *node)
209
217
node -> left_child = new_root -> right_child ;
210
218
new_root -> right_child = node ;
211
219
220
+ /* Update parent references */
221
+
222
+ node -> parent = new_root ;
223
+
224
+ if (node -> left_child != NULL ) {
225
+ node -> left_child -> parent = node ;
226
+ }
227
+
212
228
/* Update heights of the affected nodes */
213
229
214
230
avltree_update_height (new_root );
215
231
avltree_update_height (node );
216
232
}
217
233
234
+ /* Balance a particular tree node.
235
+ *
236
+ * Returns the root node of the new subtree which is replacing the
237
+ * old one. */
238
+
239
+ static AVLTreeNode * avltree_node_balance (AVLTree * tree , AVLTreeNode * node )
240
+ {
241
+ AVLTreeNode * new_root ;
242
+ int diff ;
243
+
244
+ /* Check the heights of the child trees. If there is an unbalance
245
+ * (difference between left and right > 2), then rotate nodes
246
+ * around to fix it */
247
+
248
+ diff = avltree_subtree_height (node -> right_child )
249
+ - avltree_subtree_height (node -> left_child );
250
+
251
+ if (diff >= 2 ) {
252
+
253
+ /* Biased toward the right side too much. */
254
+
255
+ if (avltree_subtree_height (node -> right_child -> right_child )
256
+ <= avltree_subtree_height (node -> right_child -> left_child )) {
257
+
258
+ /* If the right child is biased toward the left
259
+ * side, it must be rotated right first (double
260
+ * rotation) */
261
+
262
+ avltree_rotate_right (tree , node -> right_child );
263
+ }
264
+
265
+ /* Perform a left rotation. After this, the right child will
266
+ * take the place of this node. Store a pointer to the right
267
+ * child so that we can continue where we left off. */
268
+
269
+ new_root = node -> right_child ;
270
+
271
+ avltree_rotate_left (tree , node );
272
+
273
+ node = new_root ;
274
+
275
+ } else if (diff <= -2 ) {
276
+
277
+ /* Biased toward the left side too much. */
278
+
279
+ if (avltree_subtree_height (node -> left_child -> left_child )
280
+ <= avltree_subtree_height (node -> left_child -> right_child )) {
281
+
282
+ /* If the left child is biased toward the right
283
+ * side, it must be rotated right left (double
284
+ * rotation) */
285
+
286
+ avltree_rotate_left (tree , node -> left_child );
287
+ }
288
+
289
+ /* Perform a right rotation. After this, the left child
290
+ * will take the place of this node. Store a pointer to the
291
+ * left child so that we can continue where we left off. */
292
+
293
+ new_root = node -> left_child ;
294
+
295
+ avltree_rotate_right (tree , node );
296
+
297
+ node = new_root ;
298
+ }
299
+
300
+ /* Update the height of this node */
301
+
302
+ avltree_update_height (node );
303
+
304
+ return node ;
305
+ }
306
+
218
307
AVLTreeNode * avltree_insert (AVLTree * tree , void * key , void * value )
219
308
{
220
309
AVLTreeNode * * rover ;
221
310
AVLTreeNode * new_node ;
222
311
AVLTreeNode * previous_node ;
223
312
AVLTreeNode * node ;
224
- AVLTreeNode * new_root ;
225
- int diff ;
226
313
227
314
/* Walk down the tree until we reach a NULL pointer */
228
315
@@ -258,68 +345,167 @@ AVLTreeNode *avltree_insert(AVLTree *tree, void *key, void *value)
258
345
259
346
while (node != NULL ) {
260
347
261
- /* Check the heights of the child trees. If there is an unbalance
262
- * (difference between left and right > 2), then rotate nodes
263
- * around to fix it */
348
+ /* Balance this node if necessary */
264
349
265
- diff = avltree_subtree_height (node -> right_child )
266
- - avltree_subtree_height (node -> left_child );
350
+ node = avltree_node_balance (tree , node );
267
351
268
- if (diff >= 2 ) {
269
-
270
- /* Biased toward the right side too much. */
352
+ /* Go to this node's parent */
271
353
272
- if (tree -> compare_func (key , node -> right_child -> key ) <= 0 ) {
354
+ node = node -> parent ;
355
+ }
273
356
274
- /* If this was added to the left of the right child,
275
- * rotate the right child right first (double rotation) */
357
+ return new_node ;
358
+ }
276
359
277
- avltree_rotate_right (tree , node -> right_child );
278
- }
360
+ /* Remove a node from a tree */
279
361
280
- /* Perform a left rotation. After this, the right child will
281
- * take the place of this node. Store a pointer to the right
282
- * child so that we can continue where we left off. */
362
+ void avltree_remove_node (AVLTree * tree , AVLTreeNode * node )
363
+ {
364
+ AVLTreeNode * swap_node ;
365
+ AVLTreeNode * rover ;
366
+ AVLTreeNode * balance_startpoint ;
283
367
284
- new_root = node -> right_child ;
285
-
286
- avltree_rotate_left (tree , node );
368
+ /* The node to be removed must be swapped with an "adjacent"
369
+ * node, ie. one which has the closest key to this one. Find
370
+ * a node to swap with. */
371
+
372
+ if (node -> left_child != NULL ) {
287
373
288
- node = new_root ;
374
+ /* Search for the right-most node in the left subtree, ie.
375
+ * the greatest value. */
289
376
290
- } else if (diff <= -2 ) {
377
+ swap_node = node -> left_child ;
378
+
379
+ while (swap_node -> right_child != NULL ) {
380
+ swap_node = swap_node -> right_child ;
381
+ }
291
382
292
- /* Biased toward the left side too much. */
383
+ /* Unlink the swap node, move the swap node's left
384
+ * child tree in to replace it */
10662
293
385
294
- if (tree -> compare_func (key , node -> left_child -> key ) >= 0 ) {
386
+ if (swap_node -> parent -> right_child == swap_node ) {
387
+ swap_node -> parent -> right_child
388
+ = swap_node -> left_child ;
389
+ } else {
390
+ swap_node -> parent -> left_child
391
+ = swap_node -> left_child ;
392
+ }
393
+
394
+ if (swap_node -> left_child != NULL ) {
395
+ swap_node -> left_child -> parent = swap_node -> parent ;
396
+ }
295
397
296
- /* If this was added to the right of the left child,
297
- * rotate the left child left first (double rotation) */
398
+ } else if (node -> right_child != NULL ) {
399
+
400
+ /* Search for the left-most node in the right subtree, ie.
401
+ * the least value. */
402
+
403
+ swap_node = node -> right_child ;
404
+
405
+ while (swap_node -> left_child != NULL ) {
406
+ swap_node = swap_node -> left_child ;
407
+ }
408
+
409
+ /* Unlink the swap node, move the swap node's right
410
+ * child tree in to replace it */
411
+
412
+ if (swap_node -> parent -> left_child == swap_node ) {
413
+ swap_node -> parent -> left_child
414
+ = swap_node -> right_child ;
415
+ } else {
416
+ swap_node -> parent -> right_child
417
+ = swap_node -> right_child ;
418
+ }
298
419
299
- avltree_rotate_left (tree , node -> left_child );
420
+ if (swap_node -> right_child != NULL ) {
421
+ swap_node -> right_child -> parent = swap_node -> parent ;
422
+ }
423
+
424
+ } else {
425
+ /* This is a leaf node and has no children, therefore
426
+ * it can be immediately removed. */
427
+
428
+ /* Unlink this node from its parent */
429
+
430
+ if (node -> parent != NULL ) {
431
+ if (node -> parent -> left_child == node ) {
432
+ node -> parent -> left_child = NULL ;
433
+ } else {
434
+ node -> parent -> right_child = NULL ;
300
435
}
436
+ } else {
437
+ /* Root node */
438
+
439
+ tree -> root_node = NULL ;
440
+ }
441
+
442
+ /* "swap" stage is skipped. */
301
443
302
- /* Perform a right rotation. After this, the left child
303
- * will take the place of this node. Store a pointer to the
304
- * left child so that we can continue where we left off. */
444
+ swap_node = NULL ;
305
445
306
- new_root = node -> left_child ;
446
+ /* Start balancing from the node's parent */
307
447
308
- avltree_rotate_right (tree , node );
448
+ balance_startpoint = node -> parent ;
449
+ }
450
+
451
+ /* Link the "swap" node into the tree, at the position where
452
+ * "node" previously was. */
453
+
454
+ if (swap_node != NULL ) {
455
+
456
+ /* Copy references in the node into the swap node */
457
+
458
+ swap_node -> left_child = node -> left_child ;
459
+ swap_node -> right_child = node -> right_child ;
460
+ swap_node -> parent = node -> parent ;
461
+
462
+ /* Link the parent's reference to this node */
463
+
464
+ if (node -> parent != NULL ) {
465
+ if (node -> parent -> left_child == node ) {
466
+ node -> parent -> left_child = swap_node ;
467
+ } else {
468
+ node -> parent -> right_child = swap_node ;
469
+ }
470
+ } else {
471
+ /* Root of the tree */
309
472
310
- node = new_root ;
473
+ tree -> root_node = swap_node ;
311
474
}
312
475
313
- /* Update the height of this node */
476
+ /* Fix the "parent" references of child nodes */
314
477
315
- avltree_update_height (node );
478
+ if (node -> left_child != NULL ) {
479
+ node -> left_child -> parent = swap_node ;
480
+ }
481
+
482
+ if (node -> right_child != NULL ) {
483
+ node -> right_child -> parent = swap_node ;
484
+ }
316
485
317
- /* Go to this node's parent */
486
+ /* Start balancing from the swap node's former parent */
318
487
319
- node = node -> parent ;
488
+ balance_startpoint = swap_node -> parent ;
320
489
}
321
490
322
- return new_node ;
491
+ /* Destroy the node */
492
+
493
+ free (node );
494
+
495
+ /* Rebalance the tree */
496
+
497
+ rover = balance_startpoint ;
498
+
499
+ while (rover != NULL ) {
500
+
501
+ /* Possibly rebalance this subtree */
502
+
503
+ rover = avltree_node_balance (tree , rover );
504
+
505
+ /* Go to the node's parent */
506
+
507
+ rover = rover -> parent ;
508
+ }
323
509
}
324
510
325
511
AVLTreeNode * avltree_lookup_node (AVLTree * tree , void * key )
@@ -369,6 +555,12 @@ void *avltree_lookup(AVLTree *tree, void *key)
369
555
}
370
556
}
371
557
558
+ AVLTreeNode * avltree_root_node (AVLTree * tree )
559
+ {
560
+ return tree -> root_node ;
561
+ }
562
+
563
+
372
564
void * avltree_node_key (AVLTreeNode * node )
373
565
{
374
566
return node -> key ;
@@ -394,54 +586,3 @@ AVLTreeNode *avltree_node_parent(AVLTreeNode *node)
394
586
return node -> parent ;
395
587
}
396
588
397
- /* !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! */
398
-
399
- /* The following all needs to be removed eventually */
400
-
401
- static void avltree_print_tree_node (AVLTreeNode * node , int indent )
402
- {
403
- int i ;
404
-
405
- if (node == NULL ) {
406
- return ;
407
- }
408
-
409
- for (i = 0 ; i < indent ; ++ i ) {
410
- putchar (' ' );
411
- }
412
-
413
- printf ("node:\n" );
414
-
415
- avltree_print_tree_node (node -> left_child , indent + 2 );
416
- avltree_print_tree_node (node -> right_child , indent + 2 );
417
- }
418
DEC7
-
419
- void avltree_print_tree (AVLTree * tree )
420
- {
421
- avltree_print_tree_node (tree -> root_node , 0 );
422
- }
423
-
424
- static int avltree_check_node_balanced (AVLTreeNode * node )
425
- {
426
- int diff ;
427
-
428
- if (node == NULL ) {
429
- return 1 ;
430
- }
431
-
432
- avltree_check_node_balanced (node -> left_child );
433
- avltree_check_node_balanced (node -> right_child );
434
-
435
- avltree_update_height (node );
436
-
437
- diff = avltree_subtree_height (node -> left_child )
438
- - avltree_subtree_height (node -> right_child );
439
-
440
- return diff > -2 && diff < 2 ;
441
- }
442
-
443
- int avltree_check_balanced (AVLTree * tree )
444
- {
445
- return avltree_check_node_balanced (tree -> root_node );
446
- }
447
-
0 commit comments