10Sstevel@tonic-gate #ifndef LINT 2*11038SRao.Shoaib@Sun.COM static const char rcsid[] = "$Id: tree.c,v 1.4 2005/04/27 04:56:39 sra Exp $"; 30Sstevel@tonic-gate #endif 40Sstevel@tonic-gate 5*11038SRao.Shoaib@Sun.COM /*% 60Sstevel@tonic-gate * tree - balanced binary tree library 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * vix 05apr94 [removed vixie.h dependencies; cleaned up formatting, names] 90Sstevel@tonic-gate * vix 22jan93 [revisited; uses RCS, ANSI, POSIX; has bug fixes] 100Sstevel@tonic-gate * vix 23jun86 [added delete uar to add for replaced nodes] 110Sstevel@tonic-gate * vix 20jun86 [added tree_delete per wirth a+ds (mod2 v.) p. 224] 120Sstevel@tonic-gate * vix 06feb86 [added tree_mung()] 130Sstevel@tonic-gate * vix 02feb86 [added tree balancing from wirth "a+ds=p" p. 220-221] 140Sstevel@tonic-gate * vix 14dec85 [written] 150Sstevel@tonic-gate */ 160Sstevel@tonic-gate 17*11038SRao.Shoaib@Sun.COM /*% 180Sstevel@tonic-gate * This program text was created by Paul Vixie using examples from the book: 190Sstevel@tonic-gate * "Algorithms & Data Structures," Niklaus Wirth, Prentice-Hall, 1986, ISBN 200Sstevel@tonic-gate * 0-13-022005-1. Any errors in the conversion from Modula-2 to C are Paul 210Sstevel@tonic-gate * Vixie's. 220Sstevel@tonic-gate */ 230Sstevel@tonic-gate 240Sstevel@tonic-gate /* 25*11038SRao.Shoaib@Sun.COM * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC") 260Sstevel@tonic-gate * Portions Copyright (c) 1996-1999 by Internet Software Consortium. 270Sstevel@tonic-gate * 280Sstevel@tonic-gate * Permission to use, copy, modify, and distribute this software for any 290Sstevel@tonic-gate * purpose with or without fee is hereby granted, provided that the above 300Sstevel@tonic-gate * copyright notice and this permission notice appear in all copies. 310Sstevel@tonic-gate * 32*11038SRao.Shoaib@Sun.COM * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES 33*11038SRao.Shoaib@Sun.COM * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 34*11038SRao.Shoaib@Sun.COM * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR 35*11038SRao.Shoaib@Sun.COM * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 36*11038SRao.Shoaib@Sun.COM * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 37*11038SRao.Shoaib@Sun.COM * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT 38*11038SRao.Shoaib@Sun.COM * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 390Sstevel@tonic-gate */ 400Sstevel@tonic-gate 410Sstevel@tonic-gate /*#define DEBUG "tree"*/ 420Sstevel@tonic-gate 430Sstevel@tonic-gate #include "port_before.h" 440Sstevel@tonic-gate 450Sstevel@tonic-gate #include <stdio.h> 460Sstevel@tonic-gate #include <stdlib.h> 470Sstevel@tonic-gate 480Sstevel@tonic-gate #include "port_after.h" 490Sstevel@tonic-gate 500Sstevel@tonic-gate #include <isc/memcluster.h> 510Sstevel@tonic-gate #include <isc/tree.h> 520Sstevel@tonic-gate 530Sstevel@tonic-gate #ifdef DEBUG 540Sstevel@tonic-gate static int debugDepth = 0; 550Sstevel@tonic-gate static char *debugFuncs[256]; 560Sstevel@tonic-gate # define ENTER(proc) { \ 570Sstevel@tonic-gate debugFuncs[debugDepth] = proc; \ 580Sstevel@tonic-gate fprintf(stderr, "ENTER(%d:%s.%s)\n", \ 590Sstevel@tonic-gate debugDepth, DEBUG, \ 600Sstevel@tonic-gate debugFuncs[debugDepth]); \ 610Sstevel@tonic-gate debugDepth++; \ 620Sstevel@tonic-gate } 630Sstevel@tonic-gate # define RET(value) { \ 640Sstevel@tonic-gate debugDepth--; \ 650Sstevel@tonic-gate fprintf(stderr, "RET(%d:%s.%s)\n", \ 660Sstevel@tonic-gate debugDepth, DEBUG, \ 670Sstevel@tonic-gate debugFuncs[debugDepth]); \ 680Sstevel@tonic-gate return (value); \ 690Sstevel@tonic-gate } 700Sstevel@tonic-gate # define RETV { \ 710Sstevel@tonic-gate debugDepth--; \ 720Sstevel@tonic-gate fprintf(stderr, "RETV(%d:%s.%s)\n", \ 730Sstevel@tonic-gate debugDepth, DEBUG, \ 740Sstevel@tonic-gate debugFuncs[debugDepth]); \ 750Sstevel@tonic-gate return; \ 760Sstevel@tonic-gate } 770Sstevel@tonic-gate # define MSG(msg) fprintf(stderr, "MSG(%s)\n", msg); 780Sstevel@tonic-gate #else 790Sstevel@tonic-gate # define ENTER(proc) ; 800Sstevel@tonic-gate # define RET(value) return (value); 810Sstevel@tonic-gate # define RETV return; 820Sstevel@tonic-gate # define MSG(msg) ; 830Sstevel@tonic-gate #endif 840Sstevel@tonic-gate 850Sstevel@tonic-gate #ifndef TRUE 860Sstevel@tonic-gate # define TRUE 1 870Sstevel@tonic-gate # define FALSE 0 880Sstevel@tonic-gate #endif 890Sstevel@tonic-gate 900Sstevel@tonic-gate static tree * sprout(tree **, tree_t, int *, int (*)(), void (*)()); 910Sstevel@tonic-gate static int delete(tree **, int (*)(), tree_t, void (*)(), int *, int *); 920Sstevel@tonic-gate static void del(tree **, int *, tree **, void (*)(), int *); 930Sstevel@tonic-gate static void bal_L(tree **, int *); 940Sstevel@tonic-gate static void bal_R(tree **, int *); 950Sstevel@tonic-gate 960Sstevel@tonic-gate void 970Sstevel@tonic-gate tree_init(tree **ppr_tree) { 980Sstevel@tonic-gate ENTER("tree_init") 990Sstevel@tonic-gate *ppr_tree = NULL; 1000Sstevel@tonic-gate RETV 1010Sstevel@tonic-gate } 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate tree_t 1040Sstevel@tonic-gate tree_srch(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), tree_t p_user) { 1050Sstevel@tonic-gate ENTER("tree_srch") 1060Sstevel@tonic-gate 1070Sstevel@tonic-gate if (*ppr_tree) { 1080Sstevel@tonic-gate int i_comp = (*pfi_compare)(p_user, (**ppr_tree).data); 1090Sstevel@tonic-gate 1100Sstevel@tonic-gate if (i_comp > 0) 1110Sstevel@tonic-gate RET(tree_srch(&(**ppr_tree).right, 1120Sstevel@tonic-gate pfi_compare, 1130Sstevel@tonic-gate p_user)) 1140Sstevel@tonic-gate 1150Sstevel@tonic-gate if (i_comp < 0) 1160Sstevel@tonic-gate RET(tree_srch(&(**ppr_tree).left, 1170Sstevel@tonic-gate pfi_compare, 1180Sstevel@tonic-gate p_user)) 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* not higher, not lower... this must be the one. 1210Sstevel@tonic-gate */ 1220Sstevel@tonic-gate RET((**ppr_tree).data) 1230Sstevel@tonic-gate } 1240Sstevel@tonic-gate 1250Sstevel@tonic-gate /* grounded. NOT found. 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate RET(NULL) 1280Sstevel@tonic-gate } 1290Sstevel@tonic-gate 1300Sstevel@tonic-gate tree_t 1310Sstevel@tonic-gate tree_add(tree **ppr_tree, int (*pfi_compare)(tree_t, tree_t), 1320Sstevel@tonic-gate tree_t p_user, void (*pfv_uar)()) 1330Sstevel@tonic-gate { 1340Sstevel@tonic-gate int i_balance = FALSE; 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate ENTER("tree_add") 1370Sstevel@tonic-gate if (!sprout(ppr_tree, p_user, &i_balance, pfi_compare, pfv_uar)) 1380Sstevel@tonic-gate RET(NULL) 1390Sstevel@tonic-gate RET(p_user) 1400Sstevel@tonic-gate } 1410Sstevel@tonic-gate 1420Sstevel@tonic-gate int 1430Sstevel@tonic-gate tree_delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), 1440Sstevel@tonic-gate tree_t p_user, void (*pfv_uar)()) 1450Sstevel@tonic-gate { 1460Sstevel@tonic-gate int i_balance = FALSE, i_uar_called = FALSE; 1470Sstevel@tonic-gate 1480Sstevel@tonic-gate ENTER("tree_delete"); 1490Sstevel@tonic-gate RET(delete(ppr_p, pfi_compare, p_user, pfv_uar, 1500Sstevel@tonic-gate &i_balance, &i_uar_called)) 1510Sstevel@tonic-gate } 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate int 1540Sstevel@tonic-gate tree_trav(tree **ppr_tree, int (*pfi_uar)(tree_t)) { 1550Sstevel@tonic-gate ENTER("tree_trav") 1560Sstevel@tonic-gate 1570Sstevel@tonic-gate if (!*ppr_tree) 1580Sstevel@tonic-gate RET(TRUE) 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate if (!tree_trav(&(**ppr_tree).left, pfi_uar)) 1610Sstevel@tonic-gate RET(FALSE) 1620Sstevel@tonic-gate if (!(*pfi_uar)((**ppr_tree).data)) 1630Sstevel@tonic-gate RET(FALSE) 1640Sstevel@tonic-gate if (!tree_trav(&(**ppr_tree).right, pfi_uar)) 1650Sstevel@tonic-gate RET(FALSE) 1660Sstevel@tonic-gate RET(TRUE) 1670Sstevel@tonic-gate } 1680Sstevel@tonic-gate 1690Sstevel@tonic-gate void 1700Sstevel@tonic-gate tree_mung(tree **ppr_tree, void (*pfv_uar)(tree_t)) { 1710Sstevel@tonic-gate ENTER("tree_mung") 1720Sstevel@tonic-gate if (*ppr_tree) { 1730Sstevel@tonic-gate tree_mung(&(**ppr_tree).left, pfv_uar); 1740Sstevel@tonic-gate tree_mung(&(**ppr_tree).right, pfv_uar); 1750Sstevel@tonic-gate if (pfv_uar) 1760Sstevel@tonic-gate (*pfv_uar)((**ppr_tree).data); 1770Sstevel@tonic-gate memput(*ppr_tree, sizeof(tree)); 1780Sstevel@tonic-gate *ppr_tree = NULL; 1790Sstevel@tonic-gate } 1800Sstevel@tonic-gate RETV 1810Sstevel@tonic-gate } 1820Sstevel@tonic-gate 1830Sstevel@tonic-gate static tree * 1840Sstevel@tonic-gate sprout(tree **ppr, tree_t p_data, int *pi_balance, 1850Sstevel@tonic-gate int (*pfi_compare)(tree_t, tree_t), void (*pfv_delete)(tree_t)) 1860Sstevel@tonic-gate { 1870Sstevel@tonic-gate tree *p1, *p2, *sub; 1880Sstevel@tonic-gate int cmp; 1890Sstevel@tonic-gate 1900Sstevel@tonic-gate ENTER("sprout") 1910Sstevel@tonic-gate 1920Sstevel@tonic-gate /* are we grounded? if so, add the node "here" and set the rebalance 1930Sstevel@tonic-gate * flag, then exit. 1940Sstevel@tonic-gate */ 1950Sstevel@tonic-gate if (!*ppr) { 1960Sstevel@tonic-gate MSG("grounded. adding new node, setting h=true") 1970Sstevel@tonic-gate *ppr = (tree *) memget(sizeof(tree)); 1980Sstevel@tonic-gate if (*ppr) { 1990Sstevel@tonic-gate (*ppr)->left = NULL; 2000Sstevel@tonic-gate (*ppr)->right = NULL; 2010Sstevel@tonic-gate (*ppr)->bal = 0; 2020Sstevel@tonic-gate (*ppr)->data = p_data; 2030Sstevel@tonic-gate *pi_balance = TRUE; 2040Sstevel@tonic-gate } 2050Sstevel@tonic-gate RET(*ppr); 2060Sstevel@tonic-gate } 2070Sstevel@tonic-gate 2080Sstevel@tonic-gate /* compare the data using routine passed by caller. 2090Sstevel@tonic-gate */ 2100Sstevel@tonic-gate cmp = (*pfi_compare)(p_data, (*ppr)->data); 2110Sstevel@tonic-gate 2120Sstevel@tonic-gate /* if LESS, prepare to move to the left. 2130Sstevel@tonic-gate */ 2140Sstevel@tonic-gate if (cmp < 0) { 2150Sstevel@tonic-gate MSG("LESS. sprouting left.") 2160Sstevel@tonic-gate sub = sprout(&(*ppr)->left, p_data, pi_balance, 2170Sstevel@tonic-gate pfi_compare, pfv_delete); 218*11038SRao.Shoaib@Sun.COM if (sub && *pi_balance) { /*%< left branch has grown */ 2190Sstevel@tonic-gate MSG("LESS: left branch has grown") 2200Sstevel@tonic-gate switch ((*ppr)->bal) { 2210Sstevel@tonic-gate case 1: 2220Sstevel@tonic-gate /* right branch WAS longer; bal is ok now */ 2230Sstevel@tonic-gate MSG("LESS: case 1.. bal restored implicitly") 2240Sstevel@tonic-gate (*ppr)->bal = 0; 2250Sstevel@tonic-gate *pi_balance = FALSE; 2260Sstevel@tonic-gate break; 2270Sstevel@tonic-gate case 0: 2280Sstevel@tonic-gate /* balance WAS okay; now left branch longer */ 2290Sstevel@tonic-gate MSG("LESS: case 0.. balnce bad but still ok") 2300Sstevel@tonic-gate (*ppr)->bal = -1; 2310Sstevel@tonic-gate break; 2320Sstevel@tonic-gate case -1: 2330Sstevel@tonic-gate /* left branch was already too long. rebal */ 2340Sstevel@tonic-gate MSG("LESS: case -1: rebalancing") 2350Sstevel@tonic-gate p1 = (*ppr)->left; 236*11038SRao.Shoaib@Sun.COM if (p1->bal == -1) { /*%< LL */ 2370Sstevel@tonic-gate MSG("LESS: single LL") 2380Sstevel@tonic-gate (*ppr)->left = p1->right; 2390Sstevel@tonic-gate p1->right = *ppr; 2400Sstevel@tonic-gate (*ppr)->bal = 0; 2410Sstevel@tonic-gate *ppr = p1; 242*11038SRao.Shoaib@Sun.COM } else { /*%< double LR */ 2430Sstevel@tonic-gate MSG("LESS: double LR") 2440Sstevel@tonic-gate 2450Sstevel@tonic-gate p2 = p1->right; 2460Sstevel@tonic-gate p1->right = p2->left; 2470Sstevel@tonic-gate p2->left = p1; 2480Sstevel@tonic-gate 2490Sstevel@tonic-gate (*ppr)->left = p2->right; 2500Sstevel@tonic-gate p2->right = *ppr; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate if (p2->bal == -1) 2530Sstevel@tonic-gate (*ppr)->bal = 1; 2540Sstevel@tonic-gate else 2550Sstevel@tonic-gate (*ppr)->bal = 0; 2560Sstevel@tonic-gate 2570Sstevel@tonic-gate if (p2->bal == 1) 2580Sstevel@tonic-gate p1->bal = -1; 2590Sstevel@tonic-gate else 2600Sstevel@tonic-gate p1->bal = 0; 2610Sstevel@tonic-gate *ppr = p2; 2620Sstevel@tonic-gate } /*else*/ 2630Sstevel@tonic-gate (*ppr)->bal = 0; 2640Sstevel@tonic-gate *pi_balance = FALSE; 2650Sstevel@tonic-gate } /*switch*/ 2660Sstevel@tonic-gate } /*if*/ 2670Sstevel@tonic-gate RET(sub) 2680Sstevel@tonic-gate } /*if*/ 2690Sstevel@tonic-gate 2700Sstevel@tonic-gate /* if MORE, prepare to move to the right. 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate if (cmp > 0) { 2730Sstevel@tonic-gate MSG("MORE: sprouting to the right") 2740Sstevel@tonic-gate sub = sprout(&(*ppr)->right, p_data, pi_balance, 2750Sstevel@tonic-gate pfi_compare, pfv_delete); 2760Sstevel@tonic-gate if (sub && *pi_balance) { 2770Sstevel@tonic-gate MSG("MORE: right branch has grown") 2780Sstevel@tonic-gate 2790Sstevel@tonic-gate switch ((*ppr)->bal) { 2800Sstevel@tonic-gate case -1: 2810Sstevel@tonic-gate MSG("MORE: balance was off, fixed implicitly") 2820Sstevel@tonic-gate (*ppr)->bal = 0; 2830Sstevel@tonic-gate *pi_balance = FALSE; 2840Sstevel@tonic-gate break; 2850Sstevel@tonic-gate case 0: 2860Sstevel@tonic-gate MSG("MORE: balance was okay, now off but ok") 2870Sstevel@tonic-gate (*ppr)->bal = 1; 2880Sstevel@tonic-gate break; 2890Sstevel@tonic-gate case 1: 2900Sstevel@tonic-gate MSG("MORE: balance was off, need to rebalance") 2910Sstevel@tonic-gate p1 = (*ppr)->right; 292*11038SRao.Shoaib@Sun.COM if (p1->bal == 1) { /*%< RR */ 2930Sstevel@tonic-gate MSG("MORE: single RR") 2940Sstevel@tonic-gate (*ppr)->right = p1->left; 2950Sstevel@tonic-gate p1->left = *ppr; 2960Sstevel@tonic-gate (*ppr)->bal = 0; 2970Sstevel@tonic-gate *ppr = p1; 298*11038SRao.Shoaib@Sun.COM } else { /*%< double RL */ 2990Sstevel@tonic-gate MSG("MORE: double RL") 3000Sstevel@tonic-gate 3010Sstevel@tonic-gate p2 = p1->left; 3020Sstevel@tonic-gate p1->left = p2->right; 3030Sstevel@tonic-gate p2->right = p1; 3040Sstevel@tonic-gate 3050Sstevel@tonic-gate (*ppr)->right = p2->left; 3060Sstevel@tonic-gate p2->left = *ppr; 3070Sstevel@tonic-gate 3080Sstevel@tonic-gate if (p2->bal == 1) 3090Sstevel@tonic-gate (*ppr)->bal = -1; 3100Sstevel@tonic-gate else 3110Sstevel@tonic-gate (*ppr)->bal = 0; 3120Sstevel@tonic-gate 3130Sstevel@tonic-gate if (p2->bal == -1) 3140Sstevel@tonic-gate p1->bal = 1; 3150Sstevel@tonic-gate else 3160Sstevel@tonic-gate p1->bal = 0; 3170Sstevel@tonic-gate 3180Sstevel@tonic-gate *ppr = p2; 3190Sstevel@tonic-gate } /*else*/ 3200Sstevel@tonic-gate (*ppr)->bal = 0; 3210Sstevel@tonic-gate *pi_balance = FALSE; 3220Sstevel@tonic-gate } /*switch*/ 3230Sstevel@tonic-gate } /*if*/ 3240Sstevel@tonic-gate RET(sub) 3250Sstevel@tonic-gate } /*if*/ 3260Sstevel@tonic-gate 3270Sstevel@tonic-gate /* not less, not more: this is the same key! replace... 3280Sstevel@tonic-gate */ 3290Sstevel@tonic-gate MSG("FOUND: Replacing data value") 3300Sstevel@tonic-gate *pi_balance = FALSE; 3310Sstevel@tonic-gate if (pfv_delete) 3320Sstevel@tonic-gate (*pfv_delete)((*ppr)->data); 3330Sstevel@tonic-gate (*ppr)->data = p_data; 3340Sstevel@tonic-gate RET(*ppr) 3350Sstevel@tonic-gate } 3360Sstevel@tonic-gate 3370Sstevel@tonic-gate static int 3380Sstevel@tonic-gate delete(tree **ppr_p, int (*pfi_compare)(tree_t, tree_t), tree_t p_user, 3390Sstevel@tonic-gate void (*pfv_uar)(tree_t), int *pi_balance, int *pi_uar_called) 3400Sstevel@tonic-gate { 3410Sstevel@tonic-gate tree *pr_q; 3420Sstevel@tonic-gate int i_comp, i_ret; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate ENTER("delete") 3450Sstevel@tonic-gate 3460Sstevel@tonic-gate if (*ppr_p == NULL) { 3470Sstevel@tonic-gate MSG("key not in tree") 3480Sstevel@tonic-gate RET(FALSE) 3490Sstevel@tonic-gate } 3500Sstevel@tonic-gate 3510Sstevel@tonic-gate i_comp = (*pfi_compare)((*ppr_p)->data, p_user); 3520Sstevel@tonic-gate if (i_comp > 0) { 3530Sstevel@tonic-gate MSG("too high - scan left") 3540Sstevel@tonic-gate i_ret = delete(&(*ppr_p)->left, pfi_compare, p_user, pfv_uar, 3550Sstevel@tonic-gate pi_balance, pi_uar_called); 3560Sstevel@tonic-gate if (*pi_balance) 3570Sstevel@tonic-gate bal_L(ppr_p, pi_balance); 3580Sstevel@tonic-gate } else if (i_comp < 0) { 3590Sstevel@tonic-gate MSG("too low - scan right") 3600Sstevel@tonic-gate i_ret = delete(&(*ppr_p)->right, pfi_compare, p_user, pfv_uar, 3610Sstevel@tonic-gate pi_balance, pi_uar_called); 3620Sstevel@tonic-gate if (*pi_balance) 3630Sstevel@tonic-gate bal_R(ppr_p, pi_balance); 3640Sstevel@tonic-gate } else { 3650Sstevel@tonic-gate MSG("equal") 3660Sstevel@tonic-gate pr_q = *ppr_p; 3670Sstevel@tonic-gate if (pr_q->right == NULL) { 3680Sstevel@tonic-gate MSG("right subtree null") 3690Sstevel@tonic-gate *ppr_p = pr_q->left; 3700Sstevel@tonic-gate *pi_balance = TRUE; 3710Sstevel@tonic-gate } else if (pr_q->left == NULL) { 3720Sstevel@tonic-gate MSG("right subtree non-null, left subtree null") 3730Sstevel@tonic-gate *ppr_p = pr_q->right; 3740Sstevel@tonic-gate *pi_balance = TRUE; 3750Sstevel@tonic-gate } else { 3760Sstevel@tonic-gate MSG("neither subtree null") 3770Sstevel@tonic-gate del(&pr_q->left, pi_balance, &pr_q, 3780Sstevel@tonic-gate pfv_uar, pi_uar_called); 3790Sstevel@tonic-gate if (*pi_balance) 3800Sstevel@tonic-gate bal_L(ppr_p, pi_balance); 3810Sstevel@tonic-gate } 3820Sstevel@tonic-gate if (!*pi_uar_called && pfv_uar) 3830Sstevel@tonic-gate (*pfv_uar)(pr_q->data); 3840Sstevel@tonic-gate /* Thanks to wuth@castrov.cuc.ab.ca for the following stmt. */ 3850Sstevel@tonic-gate memput(pr_q, sizeof(tree)); 3860Sstevel@tonic-gate i_ret = TRUE; 3870Sstevel@tonic-gate } 3880Sstevel@tonic-gate RET(i_ret) 3890Sstevel@tonic-gate } 3900Sstevel@tonic-gate 3910Sstevel@tonic-gate static void 3920Sstevel@tonic-gate del(tree **ppr_r, int *pi_balance, tree **ppr_q, 3930Sstevel@tonic-gate void (*pfv_uar)(tree_t), int *pi_uar_called) 3940Sstevel@tonic-gate { 3950Sstevel@tonic-gate ENTER("del") 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if ((*ppr_r)->right != NULL) { 3980Sstevel@tonic-gate del(&(*ppr_r)->right, pi_balance, ppr_q, 3990Sstevel@tonic-gate pfv_uar, pi_uar_called); 4000Sstevel@tonic-gate if (*pi_balance) 4010Sstevel@tonic-gate bal_R(ppr_r, pi_balance); 4020Sstevel@tonic-gate } else { 4030Sstevel@tonic-gate if (pfv_uar) 4040Sstevel@tonic-gate (*pfv_uar)((*ppr_q)->data); 4050Sstevel@tonic-gate *pi_uar_called = TRUE; 4060Sstevel@tonic-gate (*ppr_q)->data = (*ppr_r)->data; 4070Sstevel@tonic-gate *ppr_q = *ppr_r; 4080Sstevel@tonic-gate *ppr_r = (*ppr_r)->left; 4090Sstevel@tonic-gate *pi_balance = TRUE; 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 4120Sstevel@tonic-gate RETV 4130Sstevel@tonic-gate } 4140Sstevel@tonic-gate 4150Sstevel@tonic-gate static void 4160Sstevel@tonic-gate bal_L(tree **ppr_p, int *pi_balance) { 4170Sstevel@tonic-gate tree *p1, *p2; 4180Sstevel@tonic-gate int b1, b2; 4190Sstevel@tonic-gate 4200Sstevel@tonic-gate ENTER("bal_L") 4210Sstevel@tonic-gate MSG("left branch has shrunk") 4220Sstevel@tonic-gate 4230Sstevel@tonic-gate switch ((*ppr_p)->bal) { 4240Sstevel@tonic-gate case -1: 4250Sstevel@tonic-gate MSG("was imbalanced, fixed implicitly") 4260Sstevel@tonic-gate (*ppr_p)->bal = 0; 4270Sstevel@tonic-gate break; 4280Sstevel@tonic-gate case 0: 4290Sstevel@tonic-gate MSG("was okay, is now one off") 4300Sstevel@tonic-gate (*ppr_p)->bal = 1; 4310Sstevel@tonic-gate *pi_balance = FALSE; 4320Sstevel@tonic-gate break; 4330Sstevel@tonic-gate case 1: 4340Sstevel@tonic-gate MSG("was already off, this is too much") 4350Sstevel@tonic-gate p1 = (*ppr_p)->right; 4360Sstevel@tonic-gate b1 = p1->bal; 4370Sstevel@tonic-gate if (b1 >= 0) { 4380Sstevel@tonic-gate MSG("single RR") 4390Sstevel@tonic-gate (*ppr_p)->right = p1->left; 4400Sstevel@tonic-gate p1->left = *ppr_p; 4410Sstevel@tonic-gate if (b1 == 0) { 4420Sstevel@tonic-gate MSG("b1 == 0") 4430Sstevel@tonic-gate (*ppr_p)->bal = 1; 4440Sstevel@tonic-gate p1->bal = -1; 4450Sstevel@tonic-gate *pi_balance = FALSE; 4460Sstevel@tonic-gate } else { 4470Sstevel@tonic-gate MSG("b1 != 0") 4480Sstevel@tonic-gate (*ppr_p)->bal = 0; 4490Sstevel@tonic-gate p1->bal = 0; 4500Sstevel@tonic-gate } 4510Sstevel@tonic-gate *ppr_p = p1; 4520Sstevel@tonic-gate } else { 4530Sstevel@tonic-gate MSG("double RL") 4540Sstevel@tonic-gate p2 = p1->left; 4550Sstevel@tonic-gate b2 = p2->bal; 4560Sstevel@tonic-gate p1->left = p2->right; 4570Sstevel@tonic-gate p2->right = p1; 4580Sstevel@tonic-gate (*ppr_p)->right = p2->left; 4590Sstevel@tonic-gate p2->left = *ppr_p; 4600Sstevel@tonic-gate if (b2 == 1) 4610Sstevel@tonic-gate (*ppr_p)->bal = -1; 4620Sstevel@tonic-gate else 4630Sstevel@tonic-gate (*ppr_p)->bal = 0; 4640Sstevel@tonic-gate if (b2 == -1) 4650Sstevel@tonic-gate p1->bal = 1; 4660Sstevel@tonic-gate else 4670Sstevel@tonic-gate p1->bal = 0; 4680Sstevel@tonic-gate *ppr_p = p2; 4690Sstevel@tonic-gate p2->bal = 0; 4700Sstevel@tonic-gate } 4710Sstevel@tonic-gate } 4720Sstevel@tonic-gate RETV 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate static void 4760Sstevel@tonic-gate bal_R(tree **ppr_p, int *pi_balance) { 4770Sstevel@tonic-gate tree *p1, *p2; 4780Sstevel@tonic-gate int b1, b2; 4790Sstevel@tonic-gate 4800Sstevel@tonic-gate ENTER("bal_R") 4810Sstevel@tonic-gate MSG("right branch has shrunk") 4820Sstevel@tonic-gate switch ((*ppr_p)->bal) { 4830Sstevel@tonic-gate case 1: 4840Sstevel@tonic-gate MSG("was imbalanced, fixed implicitly") 4850Sstevel@tonic-gate (*ppr_p)->bal = 0; 4860Sstevel@tonic-gate break; 4870Sstevel@tonic-gate case 0: 4880Sstevel@tonic-gate MSG("was okay, is now one off") 4890Sstevel@tonic-gate (*ppr_p)->bal = -1; 4900Sstevel@tonic-gate *pi_balance = FALSE; 4910Sstevel@tonic-gate break; 4920Sstevel@tonic-gate case -1: 4930Sstevel@tonic-gate MSG("was already off, this is too much") 4940Sstevel@tonic-gate p1 = (*ppr_p)->left; 4950Sstevel@tonic-gate b1 = p1->bal; 4960Sstevel@tonic-gate if (b1 <= 0) { 4970Sstevel@tonic-gate MSG("single LL") 4980Sstevel@tonic-gate (*ppr_p)->left = p1->right; 4990Sstevel@tonic-gate p1->right = *ppr_p; 5000Sstevel@tonic-gate if (b1 == 0) { 5010Sstevel@tonic-gate MSG("b1 == 0") 5020Sstevel@tonic-gate (*ppr_p)->bal = -1; 5030Sstevel@tonic-gate p1->bal = 1; 5040Sstevel@tonic-gate *pi_balance = FALSE; 5050Sstevel@tonic-gate } else { 5060Sstevel@tonic-gate MSG("b1 != 0") 5070Sstevel@tonic-gate (*ppr_p)->bal = 0; 5080Sstevel@tonic-gate p1->bal = 0; 5090Sstevel@tonic-gate } 5100Sstevel@tonic-gate *ppr_p = p1; 5110Sstevel@tonic-gate } else { 5120Sstevel@tonic-gate MSG("double LR") 5130Sstevel@tonic-gate p2 = p1->right; 5140Sstevel@tonic-gate b2 = p2->bal; 5150Sstevel@tonic-gate p1->right = p2->left; 5160Sstevel@tonic-gate p2->left = p1; 5170Sstevel@tonic-gate (*ppr_p)->left = p2->right; 5180Sstevel@tonic-gate p2->right = *ppr_p; 5190Sstevel@tonic-gate if (b2 == -1) 5200Sstevel@tonic-gate (*ppr_p)->bal = 1; 5210Sstevel@tonic-gate else 5220Sstevel@tonic-gate (*ppr_p)->bal = 0; 5230Sstevel@tonic-gate if (b2 == 1) 5240Sstevel@tonic-gate p1->bal = -1; 5250Sstevel@tonic-gate else 5260Sstevel@tonic-gate p1->bal = 0; 5270Sstevel@tonic-gate *ppr_p = p2; 5280Sstevel@tonic-gate p2->bal = 0; 5290Sstevel@tonic-gate } 5300Sstevel@tonic-gate } 5310Sstevel@tonic-gate RETV 5320Sstevel@tonic-gate } 533*11038SRao.Shoaib@Sun.COM 534*11038SRao.Shoaib@Sun.COM /*! \file */ 535