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;
81 * gavl_balance_one - Balance One Node to Enhance Balance Factor
82 * @subtree: pointer to pointer to node for which balance is enhanced
84 * Return Value: returns nonzero value if height of subtree is lowered by one
87 gavl_balance_one(gavl_node_t **subtree)
90 gavl_node_t *n, *p, *parent;
92 #ifdef GAVL_UNBALANCED_SUPPORT
93 if(!*subtree) return 0;
94 #endif /* GAVL_UNBALANCED_SUPPORT */
95 parent=(*subtree)->parent;
96 shdiff=(*subtree)->hdiff;
101 #ifdef GAVL_UNBALANCED_SUPPORT
103 #endif /* GAVL_UNBALANCED_SUPPORT */
106 /* if(ds>dn) dn1=dn-1; else dn1=ds-2; */
107 (*subtree)->hdiff=shdiff-n->hdiff-1;
109 #ifdef GAVL_UNBALANCED_SUPPORT
113 #endif /* GAVL_UNBALANCED_SUPPORT */
116 n->right=*subtree; (*subtree)->parent=n;
117 (*subtree)->left=p; if(p) p->parent=*subtree;
118 *subtree=n; n->parent=parent;
119 GAVL_HDIFF_DEBUG(*subtree, 0);
122 #ifdef GAVL_UNBALANCED_SUPPORT
124 #endif /* GAVL_UNBALANCED_SUPPORT */
127 /* ds1=ds-2-dp; dn1=dn+1; dp1=min(dp;ds-2); */
128 (*subtree)->hdiff=shdiff-p->hdiff;
130 #ifndef GAVL_UNBALANCED_SUPPORT
132 #else /* GAVL_UNBALANCED_SUPPORT */
133 if (p->hdiff>shdiff) p->hdiff=shdiff;
134 #endif /* GAVL_UNBALANCED_SUPPORT */
136 /* ds1=ds-2; dn1=dn+1-dp; dp1=max(dn+1;dp); */
137 (*subtree)->hdiff=shdiff;
138 shdiff=n->hdiff; /* shdiff reused for nhdiff */
139 n->hdiff=shdiff+1-p->hdiff;
140 #ifndef GAVL_UNBALANCED_SUPPORT
142 #else /* GAVL_UNBALANCED_SUPPORT */
143 if (p->hdiff<=shdiff) p->hdiff=shdiff+1;
144 #endif /* GAVL_UNBALANCED_SUPPORT */
146 n->right=p->left; if(p->left) p->left->parent=n;
147 (*subtree)->left=p->right; if(p->right) p->right->parent=*subtree;
148 p->left=n; n->parent=p;
149 p->right=*subtree; (*subtree)->parent=p;
150 *subtree=p; p->parent=parent;
151 GAVL_HDIFF_DEBUG(*subtree, 0);
158 #ifdef GAVL_UNBALANCED_SUPPORT
160 #endif /* GAVL_UNBALANCED_SUPPORT */
163 /* if(ds<dn) dn1=dn+1; else dn1=ds+2; */
164 (*subtree)->hdiff=shdiff-n->hdiff+1;
166 #ifdef GAVL_UNBALANCED_SUPPORT
170 #endif /* GAVL_UNBALANCED_SUPPORT */
173 n->left=*subtree; (*subtree)->parent=n;
174 (*subtree)->right=p; if(p) p->parent=*subtree;
175 *subtree=n; n->parent=parent;
176 GAVL_HDIFF_DEBUG(*subtree, 0);
179 #ifdef GAVL_UNBALANCED_SUPPORT
181 #endif /* GAVL_UNBALANCED_SUPPORT */
184 /* ds1=ds+2-dp; dn1=dn-1; dp1=max(dp;ds+2); */
185 (*subtree)->hdiff=shdiff-p->hdiff;
187 #ifndef GAVL_UNBALANCED_SUPPORT
189 #else /* GAVL_UNBALANCED_SUPPORT */
190 if (p->hdiff<shdiff) p->hdiff=shdiff;
191 #endif /* GAVL_UNBALANCED_SUPPORT */
193 /* ds1=ds+2; dn1=dn-1-dp; dp1=min(dn-1;dp); */
194 (*subtree)->hdiff=shdiff;
195 shdiff=n->hdiff; /* shdiff reused for nhdiff */
196 n->hdiff=shdiff-1-p->hdiff;
197 #ifndef GAVL_UNBALANCED_SUPPORT
199 #else /* GAVL_UNBALANCED_SUPPORT */
200 if (p->hdiff>=shdiff) p->hdiff=shdiff-1;
201 #endif /* GAVL_UNBALANCED_SUPPORT */
203 n->left=p->right; if(p->right) p->right->parent=n;
204 (*subtree)->right=p->left; if(p->left) p->left->parent=*subtree;
205 p->right=n; n->parent=p;
206 p->left=*subtree; (*subtree)->parent=p;
207 *subtree=p; p->parent=parent;
208 GAVL_HDIFF_DEBUG(*subtree, 0);
213 /*printf("#%d",ret);*/
218 * gavl_insert_primitive_at - Low Lewel Routine to Insert Node into Tree
219 * @root_nodep: pointer to pointer to GAVL tree root node
220 * @node: pointer to inserted node
221 * @where: pointer to found parent node
222 * @leftright: left (>=1) or right (<=0) branch
224 * This function can be used for implementing AVL trees with custom
225 * root definition. The value of the selected @left or @right pointer
226 * of provided @node has to be NULL before insert operation,
227 * i.e. node has to be end node in the selected direction.
228 * Return Value: positive value informs about success
231 gavl_insert_primitive_at(gavl_node_t **root_nodep, gavl_node_t *node,
232 gavl_node_t *where, int leftright)
237 node->left=node->right=0;
245 where->left=node; /* where->avl+=1 */
247 where->right=node; /* where->avl-=1 */
251 if(where->left==node){
252 /* break if balance enhanced */
253 if(where->hdiff++ <0) break;
255 /* break if balance enhanced */
256 if(where->hdiff-- >0) break;
264 else if(where->left==node)
268 /* if only balanced trees are supposed, then next operation
269 leads to loop break for all possible cases */
270 if(gavl_balance_one(np)) break;
278 * gavl_delete_primitive - Low Lewel Deletes/Unlinks Node from GAVL Tree
279 * @root_nodep: pointer to pointer to GAVL tree root node
280 * @node: pointer to deleted node
282 * Return Value: positive value informs about success.
285 gavl_delete_primitive(gavl_node_t **root_nodep, gavl_node_t *node)
294 if(node==*root_nodep){
297 }else if(p->left==node){
309 /* Right child only */
311 node->right->parent=p;
315 /* Left child only */
317 node->left->parent=p;
322 /* Use nearest left node for top of subtree */
323 np=&node->left; n=*np;
324 while(n->right) {np=&n->right; n=*np;}
326 if((*np=n->left)) n->left->parent=n->parent;
327 while(n->parent!=node){
331 if(!gavl_balance_one(&n->right)) {hdiff=0; break;}
333 if(n->hdiff++ ==0) {hdiff=0; break;}
337 if(!gavl_balance_one(&node->left)) hdiff=0;
339 neigh->hdiff=node->hdiff;
341 if(!(neigh->hdiff--)) hdiff=0;
345 /* Use nearest right node for top of subtree */
346 np=&node->right; n=*np;
347 while(n->left) {np=&n->left; n=*np;}
349 if((*np=n->right)) n->right->parent=n->parent;
350 while(n->parent!=node){
354 if(!gavl_balance_one(&n->left)) {hdiff=0; break;}
356 if(n->hdiff-- ==0) {hdiff=0; break;}
360 if(!gavl_balance_one(&node->right)) hdiff=0;
362 neigh->hdiff=node->hdiff;
364 if(!(neigh->hdiff++)) hdiff=0;
367 if((neigh->left=node->left)) neigh->left->parent=neigh;
368 if((neigh->right=node->right)) neigh->right->parent=neigh;
369 neigh->parent=node->parent;
379 gavl_balance_one(root_nodep);
383 if(!gavl_balance_one(&p->left)) break;
384 /* three cases for hdiff--
387 * -1 -> -2 => balance and recurse
390 if(!p->hdiff--) break;
393 if(!gavl_balance_one(&p->right)) break;
394 /* three cases for hdiff++
397 * +1 -> +2 => balance and recurse
400 if(!p->hdiff++) break;
404 if(p) left_fl=(p->left==n);
407 node->parent=node->left=node->right=NULL;
411 #ifdef GAVL_UNBALANCED_SUPPORT
414 * gavl_cut_first_primitive - Low Lewel Routine to Cut First Node from Tree
415 * @root_nodep: pointer to pointer to GAVL tree root node
417 * This enables fast delete of the first node without tree balancing.
418 * The resulting tree is degraded but height differences are kept consistent.
419 * Use of this function can result in height of tree maximally one greater
420 * the tree managed by optimal AVL functions.
421 * Return Value: returns the first node or NULL if the tree is empty
424 gavl_cut_first_primitive(gavl_node_t **root_nodep)
427 gavl_node_t **np=root_nodep;
428 if(!*np) return NULL;
431 if((*np=n->right)) n->right->parent=n->parent;
432 for(p=n->parent;p;p=p->parent)
433 if(p->hdiff++<0) break;
434 n->parent=n->left=n->right=NULL;
438 #endif /*GAVL_UNBALANCED_SUPPORT*/