xref: /onnv-gate/usr/src/lib/libresolv2/common/isc/tree.c (revision 11038:74b12212b8a2)
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
tree_init(tree ** ppr_tree)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
tree_srch(tree ** ppr_tree,int (* pfi_compare)(tree_t,tree_t),tree_t p_user)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
tree_add(tree ** ppr_tree,int (* pfi_compare)(tree_t,tree_t),tree_t p_user,void (* pfv_uar)())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
tree_delete(tree ** ppr_p,int (* pfi_compare)(tree_t,tree_t),tree_t p_user,void (* pfv_uar)())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
tree_trav(tree ** ppr_tree,int (* pfi_uar)(tree_t))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
tree_mung(tree ** ppr_tree,void (* pfv_uar)(tree_t))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 *
sprout(tree ** ppr,tree_t p_data,int * pi_balance,int (* pfi_compare)(tree_t,tree_t),void (* pfv_delete)(tree_t))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
delete(tree ** ppr_p,int (* pfi_compare)(tree_t,tree_t),tree_t p_user,void (* pfv_uar)(tree_t),int * pi_balance,int * pi_uar_called)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
del(tree ** ppr_r,int * pi_balance,tree ** ppr_q,void (* pfv_uar)(tree_t),int * pi_uar_called)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
bal_L(tree ** ppr_p,int * pi_balance)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
bal_R(tree ** ppr_p,int * pi_balance)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