1 1.1 christos /* $NetBSD: tree.c,v 1.1.1.2 2012/09/09 16:08:00 christos Exp $ */ 2 1.1 christos 3 1.1 christos #ifndef LINT 4 1.1.1.2 christos static const char rcsid[] = "Id: tree.c,v 1.4 2005/04/27 04:56:39 sra Exp "; 5 1.1 christos #endif 6 1.1 christos 7 1.1 christos /*% 8 1.1 christos * tree - balanced binary tree library 9 1.1 christos * 10 1.1 christos * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] 11 1.1 christos * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] 12 1.1 christos * vix 23jun86 [added delete uar to add for replaced nodes] 13 1.1 christos * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] 14 1.1 christos * vix 06feb86 [added tree_mung()] 15 1.1 christos * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] 16 1.1 christos * vix 14dec85 [written] 17 1.1 christos */ 18 1.1 christos 19 1.1 christos /*% 20 1.1 christos * This program text was created by Paul Vixie using examples from the book: 21 1.1 christos * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN 22 1.1 christos * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul 23 1.1 christos * Vixie's. 24 1.1 christos */ 25 1.1 christos 26 1.1 christos /* 27 1.1 christos * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 28 1.1 christos * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 29 1.1 christos * 30 1.1 christos * Permission to use, copy, modify, and distribute this software for any 31 1.1 christos * purpose with or without fee is hereby granted, provided that the above 32 1.1 christos * copyright notice and this permission notice appear in all copies. 33 1.1 christos * 34 1.1 christos * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 35 1.1 christos * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 36 1.1 christos * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 37 1.1 christos * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 38 1.1 christos * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 39 1.1 christos * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 40 1.1 christos * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 41 1.1 christos */ 42 1.1 christos 43 1.1 christos /*#define DEBUG "tree"*/ 44 1.1 christos 45 1.1 christos #include "port_before.h" 46 1.1 christos 47 1.1 christos #include <stdio.h> 48 1.1 christos #include <stdlib.h> 49 1.1 christos 50 1.1 christos #include "port_after.h" 51 1.1 christos 52 1.1 christos #include <isc/memcluster.h> 53 1.1 christos #include <isc/tree.h> 54 1.1 christos 55 1.1 christos #ifdef DEBUG 56 1.1 christos static int debugDepth = 0; 57 1.1 christos static char *debugFuncs[256]; 58 1.1 christos # define ENTER(proc) { \ 59 1.1 christos debugFuncs[debugDepth] = proc; \ 60 1.1 christos fprintf(stderr, "ENTER(%d:%s.%s)\n", \ 61 1.1 christos debugDepth, DEBUG, \ 62 1.1 christos debugFuncs[debugDepth]); \ 63 1.1 christos debugDepth++; \ 64 1.1 christos } 65 1.1 christos # define RET(value) { \ 66 1.1 christos debugDepth--; \ 67 1.1 christos fprintf(stderr, "RET(%d:%s.%s)\n", \ 68 1.1 christos debugDepth, DEBUG, \ 69 1.1 christos debugFuncs[debugDepth]); \ 70 1.1 christos return (value); \ 71 1.1 christos } 72 1.1 christos # define RETV { \ 73 1.1 christos debugDepth--; \ 74 1.1 christos fprintf(stderr, "RETV(%d:%s.%s)\n", \ 75 1.1 christos debugDepth, DEBUG, \ 76 1.1 christos debugFuncs[debugDepth]); \ 77 1.1 christos return; \ 78 1.1 christos } 79 1.1 christos # define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); 80 1.1 christos #else 81 1.1 christos # define ENTER(proc) ; 82 1.1 christos # define RET(value) return (value); 83 1.1 christos # define RETV return; 84 1.1 christos # define MSG(msg) ; 85 1.1 christos #endif 86 1.1 christos 87 1.1 christos #ifndef TRUE 88 1.1 christos # define TRUE 1 89 1.1 christos # define FALSE 0 90 1.1 christos #endif 91 1.1 christos 92 1.1 christos static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); 93 1.1 christos static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); 94 1.1 christos static void del(tree **, int *, tree **, void (*)(), int *); 95 1.1 christos static void bal_L(tree **, int *); 96 1.1 christos static void bal_R(tree **, int *); 97 1.1 christos 98 1.1 christos void 99 1.1 christos tree_init(tree **ppr_tree) { 100 1.1 christos ENTER("tree_init") 101 1.1 christos *ppr_tree = NULL; 102 1.1 christos RETV 103 1.1 christos } 104 1.1 christos 105 1.1 christos tree_t 106 1.1 christos tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) { 107 1.1 christos ENTER("tree_srch") 108 1.1 christos 109 1.1 christos if (*ppr_tree) { 110 1.1 christos int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); 111 1.1 christos 112 1.1 christos if (i_comp > 0) 113 1.1 christos RET(tree_srch(&(**ppr_tree).right, 114 1.1 christos pfi_compare, 115 1.1 christos p_user)) 116 1.1 christos 117 1.1 christos if (i_comp < 0) 118 1.1 christos RET(tree_srch(&(**ppr_tree).left, 119 1.1 christos pfi_compare, 120 1.1 christos p_user)) 121 1.1 christos 122 1.1 christos /* not higher, not lower... this must be the one. 123 1.1 christos */ 124 1.1 christos RET((**ppr_tree).data) 125 1.1 christos } 126 1.1 christos 127 1.1 christos /* grounded. NOT found. 128 1.1 christos */ 129 1.1 christos RET(NULL) 130 1.1 christos } 131 1.1 christos 132 1.1 christos tree_t 133 1.1 christos tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), 134 1.1 christos tree_t p_user, void (*pfv_uar)()) 135 1.1 christos { 136 1.1 christos int i_balance = FALSE; 137 1.1 christos 138 1.1 christos ENTER("tree_add") 139 1.1 christos if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) 140 1.1 christos RET(NULL) 141 1.1 christos RET(p_user) 142 1.1 christos } 143 1.1 christos 144 1.1 christos int 145 1.1 christos tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), 146 1.1 christos tree_t p_user, void (*pfv_uar)()) 147 1.1 christos { 148 1.1 christos int i_balance = FALSE, i_uar_called = FALSE; 149 1.1 christos 150 1.1 christos ENTER("tree_delete"); 151 1.1 christos RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, 152 1.1 christos &i_balance, &i_uar_called)) 153 1.1 christos } 154 1.1 christos 155 1.1 christos int 156 1.1 christos tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) { 157 1.1 christos ENTER("tree_trav") 158 1.1 christos 159 1.1 christos if (!*ppr_tree) 160 1.1 christos RET(TRUE) 161 1.1 christos 162 1.1 christos if (!tree_trav(&(**ppr_tree).left, pfi_uar)) 163 1.1 christos RET(FALSE) 164 1.1 christos if (!(*pfi_uar)((**ppr_tree).data)) 165 1.1 christos RET(FALSE) 166 1.1 christos if (!tree_trav(&(**ppr_tree).right, pfi_uar)) 167 1.1 christos RET(FALSE) 168 1.1 christos RET(TRUE) 169 1.1 christos } 170 1.1 christos 171 1.1 christos void 172 1.1 christos tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) { 173 1.1 christos ENTER("tree_mung") 174 1.1 christos if (*ppr_tree) { 175 1.1 christos tree_mung(&(**ppr_tree).left, pfv_uar); 176 1.1 christos tree_mung(&(**ppr_tree).right, pfv_uar); 177 1.1 christos if (pfv_uar) 178 1.1 christos (*pfv_uar)((**ppr_tree).data); 179 1.1 christos memput(*ppr_tree, sizeof(tree)); 180 1.1 christos *ppr_tree = NULL; 181 1.1 christos } 182 1.1 christos RETV 183 1.1 christos } 184 1.1 christos 185 1.1 christos static tree * 186 1.1 christos sprout(tree **ppr, tree_t p_data, int *pi_balance, 187 1.1 christos int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t)) 188 1.1 christos { 189 1.1 christos tree *p1, *p2, *sub; 190 1.1 christos int cmp; 191 1.1 christos 192 1.1 christos ENTER("sprout") 193 1.1 christos 194 1.1 christos /* are we grounded? if so, add the node "here" and set the rebalance 195 1.1 christos * flag, then exit. 196 1.1 christos */ 197 1.1 christos if (!*ppr) { 198 1.1 christos MSG("grounded. adding new node, setting h=true") 199 1.1 christos *ppr = (tree *) memget(sizeof(tree)); 200 1.1 christos if (*ppr) { 201 1.1 christos (*ppr)->left = NULL; 202 1.1 christos (*ppr)->right = NULL; 203 1.1 christos (*ppr)->bal = 0; 204 1.1 christos (*ppr)->data = p_data; 205 1.1 christos *pi_balance = TRUE; 206 1.1 christos } 207 1.1 christos RET(*ppr); 208 1.1 christos } 209 1.1 christos 210 1.1 christos /* compare the data using routine passed by caller. 211 1.1 christos */ 212 1.1 christos cmp = (*pfi_compare)(p_data, (*ppr)->data); 213 1.1 christos 214 1.1 christos /* if LESS, prepare to move to the left. 215 1.1 christos */ 216 1.1 christos if (cmp < 0) { 217 1.1 christos MSG("LESS. sprouting left.") 218 1.1 christos sub = sprout(&(*ppr)->left, p_data, pi_balance, 219 1.1 christos pfi_compare, pfv_delete); 220 1.1 christos if (sub && *pi_balance) { /*%< left branch has grown */ 221 1.1 christos MSG("LESS: left branch has grown") 222 1.1 christos switch ((*ppr)->bal) { 223 1.1 christos case 1: 224 1.1 christos /* right branch WAS longer; bal is ok now */ 225 1.1 christos MSG("LESS: case 1.. bal restored implicitly") 226 1.1 christos (*ppr)->bal = 0; 227 1.1 christos *pi_balance = FALSE; 228 1.1 christos break; 229 1.1 christos case 0: 230 1.1 christos /* balance WAS okay; now left branch longer */ 231 1.1 christos MSG("LESS: case 0.. balnce bad but still ok") 232 1.1 christos (*ppr)->bal = -1; 233 1.1 christos break; 234 1.1 christos case -1: 235 1.1 christos /* left branch was already too long. rebal */ 236 1.1 christos MSG("LESS: case -1: rebalancing") 237 1.1 christos p1 = (*ppr)->left; 238 1.1 christos if (p1->bal == -1) { /*%< LL */ 239 1.1 christos MSG("LESS: single LL") 240 1.1 christos (*ppr)->left = p1->right; 241 1.1 christos p1->right = *ppr; 242 1.1 christos (*ppr)->bal = 0; 243 1.1 christos *ppr = p1; 244 1.1 christos } else { /*%< double LR */ 245 1.1 christos MSG("LESS: double LR") 246 1.1 christos 247 1.1 christos p2 = p1->right; 248 1.1 christos p1->right = p2->left; 249 1.1 christos p2->left = p1; 250 1.1 christos 251 1.1 christos (*ppr)->left = p2->right; 252 1.1 christos p2->right = *ppr; 253 1.1 christos 254 1.1 christos if (p2->bal == -1) 255 1.1 christos (*ppr)->bal = 1; 256 1.1 christos else 257 1.1 christos (*ppr)->bal = 0; 258 1.1 christos 259 1.1 christos if (p2->bal == 1) 260 1.1 christos p1->bal = -1; 261 1.1 christos else 262 1.1 christos p1->bal = 0; 263 1.1 christos *ppr = p2; 264 1.1 christos } /*else*/ 265 1.1 christos (*ppr)->bal = 0; 266 1.1 christos *pi_balance = FALSE; 267 1.1 christos } /*switch*/ 268 1.1 christos } /*if*/ 269 1.1 christos RET(sub) 270 1.1 christos } /*if*/ 271 1.1 christos 272 1.1 christos /* if MORE, prepare to move to the right. 273 1.1 christos */ 274 1.1 christos if (cmp > 0) { 275 1.1 christos MSG("MORE: sprouting to the right") 276 1.1 christos sub = sprout(&(*ppr)->right, p_data, pi_balance, 277 1.1 christos pfi_compare, pfv_delete); 278 1.1 christos if (sub && *pi_balance) { 279 1.1 christos MSG("MORE: right branch has grown") 280 1.1 christos 281 1.1 christos switch ((*ppr)->bal) { 282 1.1 christos case -1: 283 1.1 christos MSG("MORE: balance was off, fixed implicitly") 284 1.1 christos (*ppr)->bal = 0; 285 1.1 christos *pi_balance = FALSE; 286 1.1 christos break; 287 1.1 christos case 0: 288 1.1 christos MSG("MORE: balance was okay, now off but ok") 289 1.1 christos (*ppr)->bal = 1; 290 1.1 christos break; 291 1.1 christos case 1: 292 1.1 christos MSG("MORE: balance was off, need to rebalance") 293 1.1 christos p1 = (*ppr)->right; 294 1.1 christos if (p1->bal == 1) { /*%< RR */ 295 1.1 christos MSG("MORE: single RR") 296 1.1 christos (*ppr)->right = p1->left; 297 1.1 christos p1->left = *ppr; 298 1.1 christos (*ppr)->bal = 0; 299 1.1 christos *ppr = p1; 300 1.1 christos } else { /*%< double RL */ 301 1.1 christos MSG("MORE: double RL") 302 1.1 christos 303 1.1 christos p2 = p1->left; 304 1.1 christos p1->left = p2->right; 305 1.1 christos p2->right = p1; 306 1.1 christos 307 1.1 christos (*ppr)->right = p2->left; 308 1.1 christos p2->left = *ppr; 309 1.1 christos 310 1.1 christos if (p2->bal == 1) 311 1.1 christos (*ppr)->bal = -1; 312 1.1 christos else 313 1.1 christos (*ppr)->bal = 0; 314 1.1 christos 315 1.1 christos if (p2->bal == -1) 316 1.1 christos p1->bal = 1; 317 1.1 christos else 318 1.1 christos p1->bal = 0; 319 1.1 christos 320 1.1 christos *ppr = p2; 321 1.1 christos } /*else*/ 322 1.1 christos (*ppr)->bal = 0; 323 1.1 christos *pi_balance = FALSE; 324 1.1 christos } /*switch*/ 325 1.1 christos } /*if*/ 326 1.1 christos RET(sub) 327 1.1 christos } /*if*/ 328 1.1 christos 329 1.1 christos /* not less, not more: this is the same key! replace... 330 1.1 christos */ 331 1.1 christos MSG("FOUND: Replacing data value") 332 1.1 christos *pi_balance = FALSE; 333 1.1 christos if (pfv_delete) 334 1.1 christos (*pfv_delete)((*ppr)->data); 335 1.1 christos (*ppr)->data = p_data; 336 1.1 christos RET(*ppr) 337 1.1 christos } 338 1.1 christos 339 1.1 christos static int 340 1.1 christos delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user, 341 1.1 christos void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called) 342 1.1 christos { 343 1.1 christos tree *pr_q; 344 1.1 christos int i_comp, i_ret; 345 1.1 christos 346 1.1 christos ENTER("delete") 347 1.1 christos 348 1.1 christos if (*ppr_p == NULL) { 349 1.1 christos MSG("key not in tree") 350 1.1 christos RET(FALSE) 351 1.1 christos } 352 1.1 christos 353 1.1 christos i_comp = (*pfi_compare)((*ppr_p)->data, p_user); 354 1.1 christos if (i_comp > 0) { 355 1.1 christos MSG("too high - scan left") 356 1.1 christos i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, 357 1.1 christos pi_balance, pi_uar_called); 358 1.1 christos if (*pi_balance) 359 1.1 christos bal_L(ppr_p, pi_balance); 360 1.1 christos } else if (i_comp < 0) { 361 1.1 christos MSG("too low - scan right") 362 1.1 christos i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, 363 1.1 christos pi_balance, pi_uar_called); 364 1.1 christos if (*pi_balance) 365 1.1 christos bal_R(ppr_p, pi_balance); 366 1.1 christos } else { 367 1.1 christos MSG("equal") 368 1.1 christos pr_q = *ppr_p; 369 1.1 christos if (pr_q->right == NULL) { 370 1.1 christos MSG("right subtree null") 371 1.1 christos *ppr_p = pr_q->left; 372 1.1 christos *pi_balance = TRUE; 373 1.1 christos } else if (pr_q->left == NULL) { 374 1.1 christos MSG("right subtree non-null, left subtree null") 375 1.1 christos *ppr_p = pr_q->right; 376 1.1 christos *pi_balance = TRUE; 377 1.1 christos } else { 378 1.1 christos MSG("neither subtree null") 379 1.1 christos del(&pr_q->left, pi_balance, &pr_q, 380 1.1 christos pfv_uar, pi_uar_called); 381 1.1 christos if (*pi_balance) 382 1.1 christos bal_L(ppr_p, pi_balance); 383 1.1 christos } 384 1.1 christos if (!*pi_uar_called && pfv_uar) 385 1.1 christos (*pfv_uar)(pr_q->data); 386 1.1 christos /* Thanks to wuth (at) castrov.cuc.ab.ca for the following stmt. */ 387 1.1 christos memput(pr_q, sizeof(tree)); 388 1.1 christos i_ret = TRUE; 389 1.1 christos } 390 1.1 christos RET(i_ret) 391 1.1 christos } 392 1.1 christos 393 1.1 christos static void 394 1.1 christos del(tree **ppr_r, int *pi_balance, tree **ppr_q, 395 1.1 christos void (*pfv_uar)(tree_t), int *pi_uar_called) 396 1.1 christos { 397 1.1 christos ENTER("del") 398 1.1 christos 399 1.1 christos if ((*ppr_r)->right != NULL) { 400 1.1 christos del(&(*ppr_r)->right, pi_balance, ppr_q, 401 1.1 christos pfv_uar, pi_uar_called); 402 1.1 christos if (*pi_balance) 403 1.1 christos bal_R(ppr_r, pi_balance); 404 1.1 christos } else { 405 1.1 christos if (pfv_uar) 406 1.1 christos (*pfv_uar)((*ppr_q)->data); 407 1.1 christos *pi_uar_called = TRUE; 408 1.1 christos (*ppr_q)->data = (*ppr_r)->data; 409 1.1 christos *ppr_q = *ppr_r; 410 1.1 christos *ppr_r = (*ppr_r)->left; 411 1.1 christos *pi_balance = TRUE; 412 1.1 christos } 413 1.1 christos 414 1.1 christos RETV 415 1.1 christos } 416 1.1 christos 417 1.1 christos static void 418 1.1 christos bal_L(tree **ppr_p, int *pi_balance) { 419 1.1 christos tree *p1, *p2; 420 1.1 christos int b1, b2; 421 1.1 christos 422 1.1 christos ENTER("bal_L") 423 1.1 christos MSG("left branch has shrunk") 424 1.1 christos 425 1.1 christos switch ((*ppr_p)->bal) { 426 1.1 christos case -1: 427 1.1 christos MSG("was imbalanced, fixed implicitly") 428 1.1 christos (*ppr_p)->bal = 0; 429 1.1 christos break; 430 1.1 christos case 0: 431 1.1 christos MSG("was okay, is now one off") 432 1.1 christos (*ppr_p)->bal = 1; 433 1.1 christos *pi_balance = FALSE; 434 1.1 christos break; 435 1.1 christos case 1: 436 1.1 christos MSG("was already off, this is too much") 437 1.1 christos p1 = (*ppr_p)->right; 438 1.1 christos b1 = p1->bal; 439 1.1 christos if (b1 >= 0) { 440 1.1 christos MSG("single RR") 441 1.1 christos (*ppr_p)->right = p1->left; 442 1.1 christos p1->left = *ppr_p; 443 1.1 christos if (b1 == 0) { 444 1.1 christos MSG("b1 == 0") 445 1.1 christos (*ppr_p)->bal = 1; 446 1.1 christos p1->bal = -1; 447 1.1 christos *pi_balance = FALSE; 448 1.1 christos } else { 449 1.1 christos MSG("b1 != 0") 450 1.1 christos (*ppr_p)->bal = 0; 451 1.1 christos p1->bal = 0; 452 1.1 christos } 453 1.1 christos *ppr_p = p1; 454 1.1 christos } else { 455 1.1 christos MSG("double RL") 456 1.1 christos p2 = p1->left; 457 1.1 christos b2 = p2->bal; 458 1.1 christos p1->left = p2->right; 459 1.1 christos p2->right = p1; 460 1.1 christos (*ppr_p)->right = p2->left; 461 1.1 christos p2->left = *ppr_p; 462 1.1 christos if (b2 == 1) 463 1.1 christos (*ppr_p)->bal = -1; 464 1.1 christos else 465 1.1 christos (*ppr_p)->bal = 0; 466 1.1 christos if (b2 == -1) 467 1.1 christos p1->bal = 1; 468 1.1 christos else 469 1.1 christos p1->bal = 0; 470 1.1 christos *ppr_p = p2; 471 1.1 christos p2->bal = 0; 472 1.1 christos } 473 1.1 christos } 474 1.1 christos RETV 475 1.1 christos } 476 1.1 christos 477 1.1 christos static void 478 1.1 christos bal_R(tree **ppr_p, int *pi_balance) { 479 1.1 christos tree *p1, *p2; 480 1.1 christos int b1, b2; 481 1.1 christos 482 1.1 christos ENTER("bal_R") 483 1.1 christos MSG("right branch has shrunk") 484 1.1 christos switch ((*ppr_p)->bal) { 485 1.1 christos case 1: 486 1.1 christos MSG("was imbalanced, fixed implicitly") 487 1.1 christos (*ppr_p)->bal = 0; 488 1.1 christos break; 489 1.1 christos case 0: 490 1.1 christos MSG("was okay, is now one off") 491 1.1 christos (*ppr_p)->bal = -1; 492 1.1 christos *pi_balance = FALSE; 493 1.1 christos break; 494 1.1 christos case -1: 495 1.1 christos MSG("was already off, this is too much") 496 1.1 christos p1 = (*ppr_p)->left; 497 1.1 christos b1 = p1->bal; 498 1.1 christos if (b1 <= 0) { 499 1.1 christos MSG("single LL") 500 1.1 christos (*ppr_p)->left = p1->right; 501 1.1 christos p1->right = *ppr_p; 502 1.1 christos if (b1 == 0) { 503 1.1 christos MSG("b1 == 0") 504 1.1 christos (*ppr_p)->bal = -1; 505 1.1 christos p1->bal = 1; 506 1.1 christos *pi_balance = FALSE; 507 1.1 christos } else { 508 1.1 christos MSG("b1 != 0") 509 1.1 christos (*ppr_p)->bal = 0; 510 1.1 christos p1->bal = 0; 511 1.1 christos } 512 1.1 christos *ppr_p = p1; 513 1.1 christos } else { 514 1.1 christos MSG("double LR") 515 1.1 christos p2 = p1->right; 516 1.1 christos b2 = p2->bal; 517 1.1 christos p1->right = p2->left; 518 1.1 christos p2->left = p1; 519 1.1 christos (*ppr_p)->left = p2->right; 520 1.1 christos p2->right = *ppr_p; 521 1.1 christos if (b2 == -1) 522 1.1 christos (*ppr_p)->bal = 1; 523 1.1 christos else 524 1.1 christos (*ppr_p)->bal = 0; 525 1.1 christos if (b2 == 1) 526 1.1 christos p1->bal = -1; 527 1.1 christos else 528 1.1 christos p1->bal = 0; 529 1.1 christos *ppr_p = p2; 530 1.1 christos p2->bal = 0; 531 1.1 christos } 532 1.1 christos } 533 1.1 christos RETV 534 1.1 christos } 535 1.1 christos 536 1.1 christos /*! \file */ 537