Home | History | Annotate | Line # | Download | only in isc
      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