1 /*******************************************************************
2 uLan Communication - C interface library
4 ul_gavlprim.c - primitives for generic AVL tree
6 (C) Copyright 2003 by Pavel Pisa - Originator
8 The uLan driver is distributed under the Gnu General Public License.
9 See file COPYING for details.
11 Originator reserve the right to use and publish sources
12 under different conditions too. If third party contributors
13 do not accept this condition, they can delete this statement
14 and only GNU license will apply.
15 *******************************************************************/
21 gavl_hdiff_check(gavl_node_t *node, int mode);
24 #define GAVL_HDIFF_DEBUG(tree, mode) gavl_hdiff_check(tree, mode)
26 #define GAVL_HDIFF_DEBUG(tree, mode)
30 * gavl_next_node - Returns Next Node of GAVL Tree
31 * @node: node for which accessor is looked for
33 * Return Value: pointer to next node of tree according to ordering
36 gavl_next_node(const gavl_node_t *node)
40 while(n->left) n=n->left;
43 while((n=node->parent)){
44 if(n->right!=node) break;
52 * gavl_prev_node - Returns Previous Node of GAVL Tree
53 * @node: node for which predecessor is looked for
55 * Return Value: pointer to previous node of tree according to ordering
58 gavl_prev_node(const gavl_node_t *node)
62 while(n->right) n=n->right;
65 while((n=node->parent)){
66 if(n->left!=node) break;
74 * gavl_balance_one - Balance One Node to Enhance Balance Factor
75 * @subtree: pointer to pointer to node for which balance is enhanced
77 * Return Value: returns nonzero value if height of subtree is lowered by one
80 gavl_balance_one(gavl_node_t **subtree)
83 gavl_node_t *n, *p, *parent;
85 #ifdef GAVL_UNBALANCED_SUPPORT
86 if(!*subtree) return 0;
87 #endif /* GAVL_UNBALANCED_SUPPORT */
88 parent=(*subtree)->parent;
89 shdiff=(*subtree)->hdiff;
94 #ifdef GAVL_UNBALANCED_SUPPORT
96 #endif /* GAVL_UNBALANCED_SUPPORT */
99 /* if(ds>dn) dn1=dn-1; else dn1=ds-2; */
100 (*subtree)->hdiff=shdiff-n->hdiff-1;
102 #ifdef GAVL_UNBALANCED_SUPPORT
106 #endif /* GAVL_UNBALANCED_SUPPORT */
109 n->right=*subtree; (*subtree)->parent=n;
110 (*subtree)->left=p; if(p) p->parent=*subtree;
111 *subtree=n; n->parent=parent;
112 GAVL_HDIFF_DEBUG(*subtree, 0);
115 #ifdef GAVL_UNBALANCED_SUPPORT
117 #endif /* GAVL_UNBALANCED_SUPPORT */
120 /* ds1=ds-2-dp; dn1=dn+1; dp1=min(dp;ds-2); */
121 (*subtree)->hdiff=shdiff-p->hdiff;
123 #ifndef GAVL_UNBALANCED_SUPPORT
125 #else /* GAVL_UNBALANCED_SUPPORT */
126 if (p->hdiff>shdiff) p->hdiff=shdiff;
127 #endif /* GAVL_UNBALANCED_SUPPORT */
129 /* ds1=ds-2; dn1=dn+1-dp; dp1=max(dn+1;dp); */
130 (*subtree)->hdiff=shdiff;
131 shdiff=n->hdiff; /* shdiff reused for nhdiff */
132 n->hdiff=shdiff+1-p->hdiff;
133 #ifndef GAVL_UNBALANCED_SUPPORT
135 #else /* GAVL_UNBALANCED_SUPPORT */
136 if (p->hdiff<=shdiff) p->hdiff=shdiff+1;
137 #endif /* GAVL_UNBALANCED_SUPPORT */
139 n->right=p->left; if(p->left) p->left->parent=n;
140 (*subtree)->left=p->right; if(p->right) p->right->parent=*subtree;
141 p->left=n; n->parent=p;
142 p->right=*subtree; (*subtree)->parent=p;
143 *subtree=p; p->parent=parent;
144 GAVL_HDIFF_DEBUG(*subtree, 0);
151 #ifdef GAVL_UNBALANCED_SUPPORT
153 #endif /* GAVL_UNBALANCED_SUPPORT */
156 /* if(ds<dn) dn1=dn+1; else dn1=ds+2; */
157 (*subtree)->hdiff=shdiff-n->hdiff+1;
159 #ifdef GAVL_UNBALANCED_SUPPORT
163 #endif /* GAVL_UNBALANCED_SUPPORT */
166 n->left=*subtree; (*subtree)->parent=n;
167 (*subtree)->right=p; if(p) p->parent=*subtree;
168 *subtree=n; n->parent=parent;
169 GAVL_HDIFF_DEBUG(*subtree, 0);
172 #ifdef GAVL_UNBALANCED_SUPPORT
174 #endif /* GAVL_UNBALANCED_SUPPORT */
177 /* ds1=ds+2-dp; dn1=dn-1; dp1=max(dp;ds+2); */
178 (*subtree)->hdiff=shdiff-p->hdiff;
180 #ifndef GAVL_UNBALANCED_SUPPORT
182 #else /* GAVL_UNBALANCED_SUPPORT */
183 if (p->hdiff<shdiff) p->hdiff=shdiff;
184 #endif /* GAVL_UNBALANCED_SUPPORT */
186 /* ds1=ds+2; dn1=dn-1-dp; dp1=min(dn-1;dp); */
187 (*subtree)->hdiff=shdiff;
188 shdiff=n->hdiff; /* shdiff reused for nhdiff */
189 n->hdiff=shdiff-1-p->hdiff;
190 #ifndef GAVL_UNBALANCED_SUPPORT
192 #else /* GAVL_UNBALANCED_SUPPORT */
193 if (p->hdiff>=shdiff) p->hdiff=shdiff-1;
194 #endif /* GAVL_UNBALANCED_SUPPORT */
196 n->left=p->right; if(p->right) p->right->parent=n;
197 (*subtree)->right=p->left; if(p->left) p->left->parent=*subtree;
198 p->right=n; n->parent=p;
199 p->left=*subtree; (*subtree)->parent=p;
200 *subtree=p; p->parent=parent;
201 GAVL_HDIFF_DEBUG(*subtree, 0);
206 /*printf("#%d",ret);*/
211 * gavl_insert_primitive_at - Low Lewel Routine to Insert Node into Tree
212 * @root_nodep: pointer to pointer to GAVL tree root node
213 * @node: pointer to inserted node
214 * @where: pointer to found parent node
215 * @leftright: left (>=1) or right (<=0) branch
217 * This function can be used for implementing AVL trees with custom
218 * root definition. The value of the selected @left or @right pointer
219 * of provided @node has to be NULL before insert operation,
220 * i.e. node has to be end node in the selected direction.
221 * Return Value: positive value informs about success
224 gavl_insert_primitive_at(gavl_node_t **root_nodep, gavl_node_t *node,
225 gavl_node_t *where, int leftright)
230 node->left=node->right=0;
238 where->left=node; /* where->avl+=1 */
240 where->right=node; /* where->avl-=1 */
244 if(where->left==node){
245 /* break if balance enhanced */
246 if(where->hdiff++ <0) break;
248 /* break if balance enhanced */
249 if(where->hdiff-- >0) break;
257 else if(where->left==node)
261 /* if only balanced trees are supposed, then next operation
262 leads to loop break for all possible cases */
263 if(gavl_balance_one(np)) break;
271 * gavl_delete_primitive - Low Lewel Deletes/Unlinks Node from GAVL Tree
272 * @root_nodep: pointer to pointer to GAVL tree root node
273 * @node: pointer to deleted node
275 * Return Value: positive value informs about success.
278 gavl_delete_primitive(gavl_node_t **root_nodep, gavl_node_t *node)
287 if(node==*root_nodep){
290 }else if(p->left==node){
302 /* Right child only */
304 node->right->parent=p;
308 /* Left child only */
310 node->left->parent=p;
315 /* Use nearest left node for top of subtree */
316 np=&node->left; n=*np;
317 while(n->right) {np=&n->right; n=*np;}
319 if((*np=n->left)) n->left->parent=n->parent;
320 while(n->parent!=node){
324 if(!gavl_balance_one(&n->right)) {hdiff=0; break;}
326 if(n->hdiff++ ==0) {hdiff=0; break;}
330 if(!gavl_balance_one(&node->left)) hdiff=0;
332 neigh->hdiff=node->hdiff;
334 if(!(neigh->hdiff--)) hdiff=0;
338 /* Use nearest right node for top of subtree */
339 np=&node->right; n=*np;
340 while(n->left) {np=&n->left; n=*np;}
342 if((*np=n->right)) n->right->parent=n->parent;
343 while(n->parent!=node){
347 if(!gavl_balance_one(&n->left)) {hdiff=0; break;}
349 if(n->hdiff-- ==0) {hdiff=0; break;}
353 if(!gavl_balance_one(&node->right)) hdiff=0;
355 neigh->hdiff=node->hdiff;
357 if(!(neigh->hdiff++)) hdiff=0;
360 if((neigh->left=node->left)) neigh->left->parent=neigh;
361 if((neigh->right=node->right)) neigh->right->parent=neigh;
362 neigh->parent=node->parent;
372 gavl_balance_one(root_nodep);
376 if(!gavl_balance_one(&p->left)) break;
377 /* three cases for hdiff--
380 * -1 -> -2 => balance and recurse
383 if(!p->hdiff--) break;
386 if(!gavl_balance_one(&p->right)) break;
387 /* three cases for hdiff++
390 * +1 -> +2 => balance and recurse
393 if(!p->hdiff++) break;
397 if(p) left_fl=(p->left==n);
400 node->parent=node->left=node->right=NULL;
404 #ifdef GAVL_UNBALANCED_SUPPORT
407 * gavl_cut_first_primitive - Low Lewel Routine to Cut First Node from Tree
408 * @root_nodep: pointer to pointer to GAVL tree root node
410 * This enables fast delete of the first node without tree balancing.
411 * The resulting tree is degraded but height differences are kept consistent.
412 * Use of this function can result in height of tree maximally one greater
413 * the tree managed by optimal AVL functions.
414 * Return Value: returns the first node or NULL if the tree is empty
417 gavl_cut_first_primitive(gavl_node_t **root_nodep)
420 gavl_node_t **np=root_nodep;
421 if(!*np) return NULL;
424 if((*np=n->right)) n->right->parent=n->parent;
425 for(p=n->parent;p;p=p->parent)
426 if(p->hdiff++<0) break;
427 n->parent=n->left=n->right=NULL;
431 #endif /*GAVL_UNBALANCED_SUPPORT*/