2 * ANSI C Library for maintainance of AVL Balanced Trees
5 * G. M. Adelson-Velskij & E. M. Landis
6 * Doklady Akad. Nauk SSSR 146 (1962), 263-266
9 * D. E. Knuth: The Art of Computer Programming Vol.3 (Sorting and Searching)
11 * (C) 2000 Daniel Nagy, Budapest University of Technology and Economics
12 * Released under GNU General Public License (GPL) version 2
23 int _avl_removeroot(avl_tree* t);
26 * Warning: no balance maintainance
28 void avl_swl(avl** root) {
37 * Warning: no balance maintainance
39 void avl_swr(avl** root) {
47 /* Balance maintainance after especially nasty swings
49 void avl_nasty(avl* root) {
50 switch (root->balance) {
52 root->left->balance = 0;
53 root->right->balance = 1;
56 root->left->balance = -1;
57 root->right->balance = 0;
60 root->left->balance = 0;
61 root->right->balance = 0;
68 /* Insert element a into the AVL tree t
69 * returns 1 if the depth of the tree has grown
70 * Warning: do not insert elements already present
72 int _avl_insert(avl_tree* t, avl* a) {
77 /* insert into an empty tree */
83 if (t->compar(t->root, a) > 0) {
84 /* insert into the left subtree */
86 avl_tree left_subtree;
87 left_subtree.root = t->root->left;
88 left_subtree.compar = t->compar;
89 if (_avl_insert(&left_subtree, a)) {
90 switch (t->root->balance--) {
96 if (t->root->left->balance < 0) {
99 t->root->right->balance = 0;
101 avl_swl(&(t->root->left));
106 t->root->left = left_subtree.root;
110 if (t->root->balance--)
115 /* insert into the right subtree */
116 if (t->root->right) {
117 avl_tree right_subtree;
118 right_subtree.root = t->root->right;
119 right_subtree.compar = t->compar;
120 if (_avl_insert(&right_subtree, a)) {
121 switch (t->root->balance++) {
127 if (t->root->right->balance > 0) {
129 t->root->balance = 0;
130 t->root->left->balance = 0;
132 avl_swr(&(t->root->right));
137 t->root->right = right_subtree.root;
141 if (t->root->balance++)
147 int avl_insert(avl_tree* t, avl* a) {
148 #ifndef AVL_WITHOUT_PTHREADS
149 #ifdef AVL_LOCK_WITH_MUTEX
150 pthread_mutex_lock(&t->mutex);
152 pthread_rwlock_wrlock(&t->rwlock);
154 #endif /* AVL_WITHOUT_PTHREADS */
156 int ret = _avl_insert(t, a);
158 #ifndef AVL_WITHOUT_PTHREADS
159 #ifdef AVL_LOCK_WITH_MUTEX
160 pthread_mutex_unlock(&t->mutex);
162 pthread_rwlock_unlock(&t->rwlock);
164 #endif /* AVL_WITHOUT_PTHREADS */
168 /* Remove an element a from the AVL tree t
169 * returns -1 if the depth of the tree has shrunk
170 * Warning: if the element is not present in the tree,
171 * returns 0 as if it had been removed succesfully.
173 int _avl_remove(avl_tree* t, avl* a) {
176 return _avl_removeroot(t);
177 b = t->compar(t->root, a);
179 /* remove from the left subtree */
181 avl_tree left_subtree;
182 if ((left_subtree.root = t->root->left)) {
183 left_subtree.compar = t->compar;
184 ch = _avl_remove(&left_subtree, a);
185 t->root->left = left_subtree.root;
187 switch (t->root->balance++) {
193 switch (t->root->right->balance) {
196 t->root->balance = -1;
197 t->root->left->balance = 1;
201 t->root->balance = 0;
202 t->root->left->balance = 0;
205 avl_swr(&(t->root->right));
213 /* remove from the right subtree */
215 avl_tree right_subtree;
216 if ((right_subtree.root = t->root->right)) {
217 right_subtree.compar = t->compar;
218 ch = _avl_remove(&right_subtree, a);
219 t->root->right = right_subtree.root;
221 switch (t->root->balance--) {
227 switch (t->root->left->balance) {
230 t->root->balance = 1;
231 t->root->right->balance = -1;
235 t->root->balance = 0;
236 t->root->right->balance = 0;
239 avl_swl(&(t->root->left));
249 int avl_remove(avl_tree* t, avl* a) {
250 #ifndef AVL_WITHOUT_PTHREADS
251 #ifdef AVL_LOCK_WITH_MUTEX
252 pthread_mutex_lock(&t->mutex);
254 pthread_rwlock_wrlock(&t->rwlock);
256 #endif /* AVL_WITHOUT_PTHREADS */
258 int ret = _avl_remove(t, a);
260 #ifndef AVL_WITHOUT_PTHREADS
261 #ifdef AVL_LOCK_WITH_MUTEX
262 pthread_mutex_unlock(&t->mutex);
264 pthread_rwlock_unlock(&t->rwlock);
266 #endif /* AVL_WITHOUT_PTHREADS */
270 /* Remove the root of the AVL tree t
271 * Warning: dumps core if t is empty
273 int _avl_removeroot(avl_tree* t) {
276 if (!t->root->left) {
277 if (!t->root->right) {
281 t->root = t->root->right;
284 if (!t->root->right) {
285 t->root = t->root->left;
288 if (t->root->balance < 0) {
289 /* remove from the left subtree */
294 /* remove from the right subtree */
299 ch = _avl_remove(t, a);
300 a->left = t->root->left;
301 a->right = t->root->right;
302 a->balance = t->root->balance;
309 int avl_removeroot(avl_tree* t) {
310 #ifndef AVL_WITHOUT_PTHREADS
311 #ifdef AVL_LOCK_WITH_MUTEX
312 pthread_mutex_lock(&t->mutex);
314 pthread_rwlock_wrlock(&t->rwlock);
316 #endif /* AVL_WITHOUT_PTHREADS */
318 int ret = _avl_removeroot(t);
320 #ifndef AVL_WITHOUT_PTHREADS
321 #ifdef AVL_LOCK_WITH_MUTEX
322 pthread_mutex_unlock(&t->mutex);
324 pthread_rwlock_unlock(&t->rwlock);
326 #endif /* AVL_WITHOUT_PTHREADS */
330 /* Iterate through elements in t from a range between a and b (inclusive)
331 * for each element calls iter(a) until it returns 0
332 * returns the last value returned by iterator or 0 if there were no calls
333 * Warning: a<=b must hold
335 int _avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl*), avl** ret) {
339 x = t->compar(t->root, a);
342 x = t->compar(t->root, b);
348 /* search in the left subtree */
349 avl_tree left_subtree;
350 if ((left_subtree.root = t->root->left)) {
351 left_subtree.compar = t->compar;
352 if (!(c = _avl_range(&left_subtree, a, b, iter, ret)))
358 if (!(c = iter(t->root))) {
365 /* search in the right subtree */
366 avl_tree right_subtree;
367 if ((right_subtree.root = t->root->right)) {
368 right_subtree.compar = t->compar;
369 if (!(c = _avl_range(&right_subtree, a, b, iter, ret)))
377 int avl_range(avl_tree* t, avl* a, avl* b, int (*iter)(avl*), avl** ret) {
378 #ifndef AVL_WITHOUT_PTHREADS
379 #ifdef AVL_LOCK_WITH_MUTEX
380 pthread_mutex_lock(&t->mutex);
382 pthread_rwlock_wrlock(&t->rwlock);
384 #endif /* AVL_WITHOUT_PTHREADS */
386 int ret2 = _avl_range(t, a, b, iter, ret);
388 #ifndef AVL_WITHOUT_PTHREADS
389 #ifdef AVL_LOCK_WITH_MUTEX
390 pthread_mutex_unlock(&t->mutex);
392 pthread_rwlock_unlock(&t->rwlock);
394 #endif /* AVL_WITHOUT_PTHREADS */
399 /* Iterate through elements in t equal to a
400 * for each element calls iter(a) until it returns 0
401 * returns the last value returned by iterator or 0 if there were no calls
403 int avl_search(avl_tree* t, avl* a, int (*iter)(avl* a), avl** ret) {
404 return avl_range(t, a, a, iter, ret);
407 void avl_init(avl_tree* t, int (*compar)(void* a, void* b)) {
411 #ifndef AVL_WITHOUT_PTHREADS
414 #ifdef AVL_LOCK_WITH_MUTEX
415 lock = pthread_mutex_init(&t->mutex, NULL);
417 lock = pthread_rwlock_init(&t->rwlock, NULL);
421 fatal("Failed to initialize AVL mutex/rwlock, error: %d", lock);
423 #endif /* AVL_WITHOUT_PTHREADS */