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 *******************************************************************/
22 gavl_hdiff_check(gavl_node_t *node, int mode);
25 #define GAVL_HDIFF_DEBUG(tree, mode) gavl_hdiff_check(tree, mode)
27 #define GAVL_HDIFF_DEBUG(tree, mode)
31 * gavl_next_node - Returns Next Node of GAVL Tree
32 * @node: node for which accessor is looked for
34 * Return Value: pointer to next node of tree according to ordering
37 gavl_next_node(const gavl_node_t *node)
41 while(n->left) n=n->left;
44 while((n=node->parent)){
45 if(n->right!=node) break;
53 * gavl_prev_node - Returns Previous Node of GAVL Tree
54 * @node: node for which predecessor is looked for
56 * Return Value: pointer to previous node of tree according to ordering
59 gavl_prev_node(const gavl_node_t *node)
63 while(n->right) n=n->right;
66 while((n=node->parent)){
67 if(n->left!=node) break;
75 * gavl_balance_one - Balance One Node to Enhance Balance Factor
76 * @subtree: pointer to pointer to node for which balance is enhanced
78 * Return Value: returns nonzero value if height of subtree is lowered by one
81 gavl_balance_one(gavl_node_t **subtree)
84 gavl_node_t *n, *p, *parent;
86 #ifdef GAVL_UNBALANCED_SUPPORT
87 if(!*subtree) return 0;
88 #endif /* GAVL_UNBALANCED_SUPPORT */
89 parent=(*subtree)->parent;
90 shdiff=(*subtree)->hdiff;
95 #ifdef GAVL_UNBALANCED_SUPPORT
97 #endif /* GAVL_UNBALANCED_SUPPORT */
100 /* if(ds>dn) dn1=dn-1; else dn1=ds-2; */
101 (*subtree)->hdiff=shdiff-n->hdiff-1;
103 #ifdef GAVL_UNBALANCED_SUPPORT
107 #endif /* GAVL_UNBALANCED_SUPPORT */
110 n->right=*subtree; (*subtree)->parent=n;
111 (*subtree)->left=p; if(p) p->parent=*subtree;
112 *subtree=n; n->parent=parent;
113 GAVL_HDIFF_DEBUG(*subtree, 0);
116 #ifdef GAVL_UNBALANCED_SUPPORT
118 #endif /* GAVL_UNBALANCED_SUPPORT */
121 /* ds1=ds-2-dp; dn1=dn+1; dp1=min(dp;ds-2); */
122 (*subtree)->hdiff=shdiff-p->hdiff;
124 #ifndef GAVL_UNBALANCED_SUPPORT
126 #else /* GAVL_UNBALANCED_SUPPORT */
127 if (p->hdiff>shdiff) p->hdiff=shdiff;
128 #endif /* GAVL_UNBALANCED_SUPPORT */
130 /* ds1=ds-2; dn1=dn+1-dp; dp1=max(dn+1;dp); */
131 (*subtree)->hdiff=shdiff;
132 shdiff=n->hdiff; /* shdiff reused for nhdiff */
133 n->hdiff=shdiff+1-p->hdiff;
134 #ifndef GAVL_UNBALANCED_SUPPORT
136 #else /* GAVL_UNBALANCED_SUPPORT */
137 if (p->hdiff<=shdiff) p->hdiff=shdiff+1;
138 #endif /* GAVL_UNBALANCED_SUPPORT */
140 n->right=p->left; if(p->left) p->left->parent=n;
141 (*subtree)->left=p->right; if(p->right) p->right->parent=*subtree;
142 p->left=n; n->parent=p;
143 p->right=*subtree; (*subtree)->parent=p;
144 *subtree=p; p->parent=parent;
145 GAVL_HDIFF_DEBUG(*subtree, 0);
152 #ifdef GAVL_UNBALANCED_SUPPORT
154 #endif /* GAVL_UNBALANCED_SUPPORT */
157 /* if(ds<dn) dn1=dn+1; else dn1=ds+2; */
158 (*subtree)->hdiff=shdiff-n->hdiff+1;
160 #ifdef GAVL_UNBALANCED_SUPPORT
164 #endif /* GAVL_UNBALANCED_SUPPORT */
167 n->left=*subtree; (*subtree)->parent=n;
168 (*subtree)->right=p; if(p) p->parent=*subtree;
169 *subtree=n; n->parent=parent;
170 GAVL_HDIFF_DEBUG(*subtree, 0);
173 #ifdef GAVL_UNBALANCED_SUPPORT
175 #endif /* GAVL_UNBALANCED_SUPPORT */
178 /* ds1=ds+2-dp; dn1=dn-1; dp1=max(dp;ds+2); */
179 (*subtree)->hdiff=shdiff-p->hdiff;
181 #ifndef GAVL_UNBALANCED_SUPPORT
183 #else /* GAVL_UNBALANCED_SUPPORT */
184 if (p->hdiff<shdiff) p->hdiff=shdiff;
185 #endif /* GAVL_UNBALANCED_SUPPORT */
187 /* ds1=ds+2; dn1=dn-1-dp; dp1=min(dn-1;dp); */
188 (*subtree)->hdiff=shdiff;
189 shdiff=n->hdiff; /* shdiff reused for nhdiff */
190 n->hdiff=shdiff-1-p->hdiff;
191 #ifndef GAVL_UNBALANCED_SUPPORT
193 #else /* GAVL_UNBALANCED_SUPPORT */
194 if (p->hdiff>=shdiff) p->hdiff=shdiff-1;
195 #endif /* GAVL_UNBALANCED_SUPPORT */
197 n->left=p->right; if(p->right) p->right->parent=n;
198 (*subtree)->right=p->left; if(p->left) p->left->parent=*subtree;
199 p->right=n; n->parent=p;
200 p->left=*subtree; (*subtree)->parent=p;
201 *subtree=p; p->parent=parent;
202 GAVL_HDIFF_DEBUG(*subtree, 0);
207 /*printf("#%d",ret);*/
212 * gavl_insert_primitive_at - Low Lewel Routine to Insert Node into Tree
213 * @root_nodep: pointer to pointer to GAVL tree root node
214 * @node: pointer to inserted node
215 * @where: pointer to found parent node
216 * @leftright: left (>=1) or right (<=0) branch
218 * This function can be used for implementing AVL trees with custom
219 * root definition. The value of the selected @left or @right pointer
220 * of provided @node has to be NULL before insert operation,
221 * i.e. node has to be end node in the selected direction.
222 * Return Value: positive value informs about success
225 gavl_insert_primitive_at(gavl_node_t **root_nodep, gavl_node_t *node,
226 gavl_node_t *where, int leftright)
231 node->left=node->right=0;
239 where->left=node; /* where->avl+=1 */
241 where->right=node; /* where->avl-=1 */
245 if(where->left==node){
246 /* break if balance enhanced */
247 if(where->hdiff++ <0) break;
249 /* break if balance enhanced */
250 if(where->hdiff-- >0) break;
258 else if(where->left==node)
262 /* if only balanced trees are supposed, then next operation
263 leads to loop break for all possible cases */
264 if(gavl_balance_one(np)) break;
272 * gavl_delete_primitive - Low Lewel Deletes/Unlinks Node from GAVL Tree
273 * @root_nodep: pointer to pointer to GAVL tree root node
274 * @node: pointer to deleted node
276 * Return Value: positive value informs about success.
279 gavl_delete_primitive(gavl_node_t **root_nodep, gavl_node_t *node)
288 if(node==*root_nodep){
291 }else if(p->left==node){
303 /* Right child only */
305 node->right->parent=p;
309 /* Left child only */
311 node->left->parent=p;
316 /* Use nearest left node for top of subtree */
317 np=&node->left; n=*np;
318 while(n->right) {np=&n->right; n=*np;}
320 if((*np=n->left)) n->left->parent=n->parent;
321 while(n->parent!=node){
325 if(!gavl_balance_one(&n->right)) {hdiff=0; break;}
327 if(n->hdiff++ ==0) {hdiff=0; break;}
331 if(!gavl_balance_one(&node->left)) hdiff=0;
333 neigh->hdiff=node->hdiff;
335 if(!(neigh->hdiff--)) hdiff=0;
339 /* Use nearest right node for top of subtree */
340 np=&node->right; n=*np;
341 while(n->left) {np=&n->left; n=*np;}
343 if((*np=n->right)) n->right->parent=n->parent;
344 while(n->parent!=node){
348 if(!gavl_balance_one(&n->left)) {hdiff=0; break;}
350 if(n->hdiff-- ==0) {hdiff=0; break;}
354 if(!gavl_balance_one(&node->right)) hdiff=0;
356 neigh->hdiff=node->hdiff;
358 if(!(neigh->hdiff++)) hdiff=0;
361 if((neigh->left=node->left)) neigh->left->parent=neigh;
362 if((neigh->right=node->right)) neigh->right->parent=neigh;
363 neigh->parent=node->parent;
373 gavl_balance_one(root_nodep);
377 if(!gavl_balance_one(&p->left)) break;
378 /* three cases for hdiff--
381 * -1 -> -2 => balance and recurse
384 if(!p->hdiff--) break;
387 if(!gavl_balance_one(&p->right)) break;
388 /* three cases for hdiff++
391 * +1 -> +2 => balance and recurse
394 if(!p->hdiff++) break;
398 if(p) left_fl=(p->left==n);
401 node->parent=node->left=node->right=NULL;
405 #ifdef GAVL_UNBALANCED_SUPPORT
408 * gavl_cut_first_primitive - Low Lewel Routine to Cut First Node from Tree
409 * @root_nodep: pointer to pointer to GAVL tree root node
411 * This enables fast delete of the first node without tree balancing.
412 * The resulting tree is degraded but height differences are kept consistent.
413 * Use of this function can result in height of tree maximally one greater
414 * the tree managed by optimal AVL functions.
415 * Return Value: returns the first node or NULL if the tree is empty
418 gavl_cut_first_primitive(gavl_node_t **root_nodep)
421 gavl_node_t **np=root_nodep;
422 if(!*np) return NULL;
425 if((*np=n->right)) n->right->parent=n->parent;
426 for(p=n->parent;p;p=p->parent)
427 if(p->hdiff++<0) break;
428 n->parent=n->left=n->right=NULL;
432 #endif /*GAVL_UNBALANCED_SUPPORT*/