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