1 /*******************************************************************
2 uLan Utilities Library - C library of basic reusable constructions
4 ul_gavlprim.c - primitives for generic AVL tree
6 (C) Copyright 2003 by Pavel Pisa - Originator
8 The uLan utilities library can be used, copied and modified under
10 - GPL - GNU General Public License
11 - LGPL - GNU Lesser General Public License
12 - MPL - Mozilla Public License
13 - and other licenses added by project originators
14 Code can be modified and re-distributed under any combination
15 of the above listed licenses. If contributor does not agree with
16 some of the licenses, he/she can delete appropriate line.
17 Warning, if you delete all lines, you are not allowed to
18 distribute source code and/or binaries utilizing code.
20 See files COPYING and README for details.
22 *******************************************************************/
28 gavl_hdiff_check(gavl_node_t *node, int mode);
31 #define GAVL_HDIFF_DEBUG(tree, mode) gavl_hdiff_check(tree, mode)
33 #define GAVL_HDIFF_DEBUG(tree, mode)
37 * gavl_next_node - Returns Next Node of GAVL Tree
38 * @node: node for which accessor is looked for
40 * Return Value: pointer to next node of tree according to ordering
43 gavl_next_node(const gavl_node_t *node)
47 while(n->left) n=n->left;
50 while((n=node->parent)){
51 if(n->right!=node) break;
59 * gavl_prev_node - Returns Previous Node of GAVL Tree
60 * @node: node for which predecessor is looked for
62 * Return Value: pointer to previous node of tree according to ordering
65 gavl_prev_node(const gavl_node_t *node)
69 while(n->right) n=n->right;
72 while((n=node->parent)){
73 if(n->left!=node) break;
80 #if defined(SDCC) || defined(__SDCC)
85 * gavl_balance_one - Balance One Node to Enhance Balance Factor
86 * @subtree: pointer to pointer to node for which balance is enhanced
88 * Return Value: returns nonzero value if height of subtree is lowered by one
91 gavl_balance_one(gavl_node_t **subtree)
94 gavl_node_t *n, *p, *parent;
96 #ifdef GAVL_UNBALANCED_SUPPORT
97 if(!*subtree) return 0;
98 #endif /* GAVL_UNBALANCED_SUPPORT */
99 parent=(*subtree)->parent;
100 shdiff=(*subtree)->hdiff;
105 #ifdef GAVL_UNBALANCED_SUPPORT
107 #endif /* GAVL_UNBALANCED_SUPPORT */
110 /* if(ds>dn) dn1=dn-1; else dn1=ds-2; */
111 (*subtree)->hdiff=shdiff-n->hdiff-1;
113 #ifdef GAVL_UNBALANCED_SUPPORT
117 #endif /* GAVL_UNBALANCED_SUPPORT */
120 n->right=*subtree; (*subtree)->parent=n;
121 (*subtree)->left=p; if(p) p->parent=*subtree;
122 *subtree=n; n->parent=parent;
123 GAVL_HDIFF_DEBUG(*subtree, 0);
126 #ifdef GAVL_UNBALANCED_SUPPORT
128 #endif /* GAVL_UNBALANCED_SUPPORT */
131 /* ds1=ds-2-dp; dn1=dn+1; dp1=min(dp;ds-2); */
132 (*subtree)->hdiff=shdiff-p->hdiff;
134 #ifndef GAVL_UNBALANCED_SUPPORT
136 #else /* GAVL_UNBALANCED_SUPPORT */
137 if (p->hdiff>shdiff) p->hdiff=shdiff;
138 #endif /* GAVL_UNBALANCED_SUPPORT */
140 /* ds1=ds-2; dn1=dn+1-dp; dp1=max(dn+1;dp); */
141 (*subtree)->hdiff=shdiff;
142 shdiff=n->hdiff; /* shdiff reused for nhdiff */
143 n->hdiff=shdiff+1-p->hdiff;
144 #ifndef GAVL_UNBALANCED_SUPPORT
146 #else /* GAVL_UNBALANCED_SUPPORT */
147 if (p->hdiff<=shdiff) p->hdiff=shdiff+1;
148 #endif /* GAVL_UNBALANCED_SUPPORT */
150 n->right=p->left; if(p->left) p->left->parent=n;
151 (*subtree)->left=p->right; if(p->right) p->right->parent=*subtree;
152 p->left=n; n->parent=p;
153 p->right=*subtree; (*subtree)->parent=p;
154 *subtree=p; p->parent=parent;
155 GAVL_HDIFF_DEBUG(*subtree, 0);
162 #ifdef GAVL_UNBALANCED_SUPPORT
164 #endif /* GAVL_UNBALANCED_SUPPORT */
167 /* if(ds<dn) dn1=dn+1; else dn1=ds+2; */
168 (*subtree)->hdiff=shdiff-n->hdiff+1;
170 #ifdef GAVL_UNBALANCED_SUPPORT
174 #endif /* GAVL_UNBALANCED_SUPPORT */
177 n->left=*subtree; (*subtree)->parent=n;
178 (*subtree)->right=p; if(p) p->parent=*subtree;
179 *subtree=n; n->parent=parent;
180 GAVL_HDIFF_DEBUG(*subtree, 0);
183 #ifdef GAVL_UNBALANCED_SUPPORT
185 #endif /* GAVL_UNBALANCED_SUPPORT */
188 /* ds1=ds+2-dp; dn1=dn-1; dp1=max(dp;ds+2); */
189 (*subtree)->hdiff=shdiff-p->hdiff;
191 #ifndef GAVL_UNBALANCED_SUPPORT
193 #else /* GAVL_UNBALANCED_SUPPORT */
194 if (p->hdiff<shdiff) p->hdiff=shdiff;
195 #endif /* GAVL_UNBALANCED_SUPPORT */
197 /* ds1=ds+2; dn1=dn-1-dp; dp1=min(dn-1;dp); */
198 (*subtree)->hdiff=shdiff;
199 shdiff=n->hdiff; /* shdiff reused for nhdiff */
200 n->hdiff=shdiff-1-p->hdiff;
201 #ifndef GAVL_UNBALANCED_SUPPORT
203 #else /* GAVL_UNBALANCED_SUPPORT */
204 if (p->hdiff>=shdiff) p->hdiff=shdiff-1;
205 #endif /* GAVL_UNBALANCED_SUPPORT */
207 n->left=p->right; if(p->right) p->right->parent=n;
208 (*subtree)->right=p->left; if(p->left) p->left->parent=*subtree;
209 p->right=n; n->parent=p;
210 p->left=*subtree; (*subtree)->parent=p;
211 *subtree=p; p->parent=parent;
212 GAVL_HDIFF_DEBUG(*subtree, 0);
217 /*printf("#%d",ret);*/
220 #if defined(SDCC) || defined(__SDCC)
225 * gavl_insert_primitive_at - Low Lewel Routine to Insert Node into Tree
226 * @root_nodep: pointer to pointer to GAVL tree root node
227 * @node: pointer to inserted node
228 * @where: pointer to found parent node
229 * @leftright: left (>=1) or right (<=0) branch
231 * This function can be used for implementing AVL trees with custom
232 * root definition. The value of the selected @left or @right pointer
233 * of provided @node has to be NULL before insert operation,
234 * i.e. node has to be end node in the selected direction.
235 * Return Value: positive value informs about success
238 gavl_insert_primitive_at(gavl_node_t **root_nodep, gavl_node_t *node,
239 gavl_node_t *where, int leftright)
244 node->left=node->right=0;
252 where->left=node; /* where->avl+=1 */
254 where->right=node; /* where->avl-=1 */
258 if(where->left==node){
259 /* break if balance enhanced */
260 if(where->hdiff++ <0) break;
262 /* break if balance enhanced */
263 if(where->hdiff-- >0) break;
271 else if(where->left==node)
275 /* if only balanced trees are supposed, then next operation
276 leads to loop break for all possible cases */
277 if(gavl_balance_one(np)) break;
285 * gavl_delete_primitive - Low Lewel Deletes/Unlinks Node from GAVL Tree
286 * @root_nodep: pointer to pointer to GAVL tree root node
287 * @node: pointer to deleted node
289 * Return Value: positive value informs about success.
292 gavl_delete_primitive(gavl_node_t **root_nodep, gavl_node_t *node)
301 if(node==*root_nodep){
304 }else if(p->left==node){
316 /* Right child only */
318 node->right->parent=p;
322 /* Left child only */
324 node->left->parent=p;
329 /* Use nearest left node for top of subtree */
330 np=&node->left; n=*np;
331 while(n->right) {np=&n->right; n=*np;}
333 if((*np=n->left)) n->left->parent=n->parent;
334 while(n->parent!=node){
338 if(!gavl_balance_one(&n->right)) {hdiff=0; break;}
340 if(n->hdiff++ ==0) {hdiff=0; break;}
344 if(!gavl_balance_one(&node->left)) hdiff=0;
346 neigh->hdiff=node->hdiff;
348 if(!(neigh->hdiff--)) hdiff=0;
352 /* Use nearest right node for top of subtree */
353 np=&node->right; n=*np;
354 while(n->left) {np=&n->left; n=*np;}
356 if((*np=n->right)) n->right->parent=n->parent;
357 while(n->parent!=node){
361 if(!gavl_balance_one(&n->left)) {hdiff=0; break;}
363 if(n->hdiff-- ==0) {hdiff=0; break;}
367 if(!gavl_balance_one(&node->right)) hdiff=0;
369 neigh->hdiff=node->hdiff;
371 if(!(neigh->hdiff++)) hdiff=0;
374 if((neigh->left=node->left)) neigh->left->parent=neigh;
375 if((neigh->right=node->right)) neigh->right->parent=neigh;
376 neigh->parent=node->parent;
386 gavl_balance_one(root_nodep);
390 if(!gavl_balance_one(&p->left)) break;
391 /* three cases for hdiff--
394 * -1 -> -2 => balance and recurse
397 if(!p->hdiff--) break;
400 if(!gavl_balance_one(&p->right)) break;
401 /* three cases for hdiff++
404 * +1 -> +2 => balance and recurse
407 if(!p->hdiff++) break;
411 if(p) left_fl=(p->left==n);
414 node->parent=node->left=node->right=NULL;
418 #ifdef GAVL_UNBALANCED_SUPPORT
421 * gavl_cut_first_primitive - Low Lewel Routine to Cut First Node from Tree
422 * @root_nodep: pointer to pointer to GAVL tree root node
424 * This enables fast delete of the first node without tree balancing.
425 * The resulting tree is degraded but height differences are kept consistent.
426 * Use of this function can result in height of tree maximally one greater
427 * the tree managed by optimal AVL functions.
428 * Return Value: returns the first node or NULL if the tree is empty
431 gavl_cut_first_primitive(gavl_node_t **root_nodep)
434 gavl_node_t **np=root_nodep;
435 if(!*np) return NULL;
438 if((*np=n->right)) n->right->parent=n->parent;
439 for(p=n->parent;p;p=p->parent)
440 if(p->hdiff++<0) break;
441 n->parent=n->left=n->right=NULL;
445 #endif /*GAVL_UNBALANCED_SUPPORT*/