src/avl.c

changeset 390
d345541018fa
parent 389
92e482410453
child 391
f094a53c1178
     1.1 --- a/src/avl.c	Mon Dec 30 09:54:10 2019 +0100
     1.2 +++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.3 @@ -1,373 +0,0 @@
     1.4 -/*
     1.5 - * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
     1.6 - *
     1.7 - * Copyright 2017 Mike Becker, Olaf Wintermann All rights reserved.
     1.8 - *
     1.9 - * Redistribution and use in source and binary forms, with or without
    1.10 - * modification, are permitted provided that the following conditions are met:
    1.11 - *
    1.12 - *   1. Redistributions of source code must retain the above copyright
    1.13 - *      notice, this list of conditions and the following disclaimer.
    1.14 - *
    1.15 - *   2. Redistributions in binary form must reproduce the above copyright
    1.16 - *      notice, this list of conditions and the following disclaimer in the
    1.17 - *      documentation and/or other materials provided with the distribution.
    1.18 - *
    1.19 - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
    1.20 - * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
    1.21 - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
    1.22 - * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
    1.23 - * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
    1.24 - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
    1.25 - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
    1.26 - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
    1.27 - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
    1.28 - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
    1.29 - * POSSIBILITY OF SUCH DAMAGE.
    1.30 - */
    1.31 -
    1.32 -#include "ucx/avl.h"
    1.33 -
    1.34 -#include <limits.h>
    1.35 -
    1.36 -#define ptrcast(ptr) ((void*)(ptr))
    1.37 -#define alloc_tree(al) (UcxAVLTree*) almalloc((al), sizeof(UcxAVLTree))
    1.38 -#define alloc_node(al) (UcxAVLNode*) almalloc((al), sizeof(UcxAVLNode))
    1.39 -
    1.40 -static void ucx_avl_connect(UcxAVLTree *tree,
    1.41 -        UcxAVLNode *node, UcxAVLNode *child, intptr_t nullkey) {
    1.42 -    if (child) {
    1.43 -        child->parent = node;
    1.44 -    }
    1.45 -    // if child is NULL, nullkey decides if left or right pointer is cleared
    1.46 -    if (tree->cmpfunc(
    1.47 -        ptrcast(child ? child->key : nullkey),
    1.48 -        ptrcast(node->key), tree->userdata) > 0) {
    1.49 -      node->right = child;
    1.50 -    } else {
    1.51 -      node->left = child;
    1.52 -    }
    1.53 -    size_t lh = node->left ? node->left->height : 0;
    1.54 -    size_t rh = node->right ? node->right->height : 0;
    1.55 -    node->height = 1 + (lh > rh ? lh : rh);
    1.56 -}
    1.57 -
    1.58 -#define avlheight(node) ((node) ? (node)->height : 0)
    1.59 -
    1.60 -static UcxAVLNode* avl_rotright(UcxAVLTree *tree, UcxAVLNode *l0) {
    1.61 -    UcxAVLNode *p = l0->parent;
    1.62 -    UcxAVLNode *l1 = l0->left;
    1.63 -    if (p) {
    1.64 -        ucx_avl_connect(tree, p, l1, 0);
    1.65 -    } else {
    1.66 -        l1->parent = NULL;
    1.67 -    }
    1.68 -    ucx_avl_connect(tree, l0, l1->right, l1->key);
    1.69 -    ucx_avl_connect(tree, l1, l0, 0);
    1.70 -    return l1;
    1.71 -}
    1.72 -
    1.73 -static UcxAVLNode* avl_rotleft(UcxAVLTree *tree, UcxAVLNode *l0) {
    1.74 -    UcxAVLNode *p = l0->parent;
    1.75 -    UcxAVLNode *l1 = l0->right;
    1.76 -    if (p) {
    1.77 -        ucx_avl_connect(tree, p, l1, 0);
    1.78 -    } else {
    1.79 -        l1->parent = NULL;
    1.80 -    }
    1.81 -    ucx_avl_connect(tree, l0, l1->left, l1->key);
    1.82 -    ucx_avl_connect(tree, l1, l0, 0);
    1.83 -    return l1;
    1.84 -}
    1.85 -
    1.86 -static void ucx_avl_balance(UcxAVLTree *tree, UcxAVLNode *n) {
    1.87 -    int lh = avlheight(n->left);
    1.88 -    int rh = avlheight(n->right);
    1.89 -    n->height = 1 + (lh > rh ? lh : rh);
    1.90 -    
    1.91 -    if (lh - rh == 2) {
    1.92 -      UcxAVLNode *c = n->left;
    1.93 -      if (avlheight(c->right) - avlheight(c->left) == 1) {
    1.94 -        avl_rotleft(tree, c);
    1.95 -      }
    1.96 -      n = avl_rotright(tree, n);
    1.97 -    } else if (rh - lh == 2) {  
    1.98 -      UcxAVLNode *c = n->right;
    1.99 -      if (avlheight(c->left) - avlheight(c->right) == 1) {
   1.100 -        avl_rotright(tree, c);
   1.101 -      }
   1.102 -      n = avl_rotleft(tree, n);
   1.103 -    }
   1.104 -
   1.105 -    if (n->parent) {
   1.106 -      ucx_avl_balance(tree, n->parent);
   1.107 -    } else {
   1.108 -      tree->root = n;
   1.109 -    }
   1.110 -}
   1.111 -
   1.112 -UcxAVLTree *ucx_avl_new(cmp_func cmpfunc) {
   1.113 -    return ucx_avl_new_a(cmpfunc, ucx_default_allocator());
   1.114 -}
   1.115 -
   1.116 -UcxAVLTree *ucx_avl_new_a(cmp_func cmpfunc, UcxAllocator *allocator) {
   1.117 -    UcxAVLTree* tree = alloc_tree(allocator);
   1.118 -    if (tree) {
   1.119 -        tree->allocator = allocator;
   1.120 -        tree->cmpfunc = cmpfunc;
   1.121 -        tree->root = NULL;
   1.122 -        tree->userdata = NULL;
   1.123 -    }
   1.124 -    
   1.125 -    return tree;
   1.126 -}
   1.127 -
   1.128 -static void ucx_avl_free_node(UcxAllocator *al, UcxAVLNode *node) {
   1.129 -    if (node) {
   1.130 -        ucx_avl_free_node(al, node->left);
   1.131 -        ucx_avl_free_node(al, node->right);
   1.132 -        alfree(al, node);
   1.133 -    }
   1.134 -}
   1.135 -
   1.136 -void ucx_avl_free(UcxAVLTree *tree) {
   1.137 -    UcxAllocator *al = tree->allocator;
   1.138 -    ucx_avl_free_node(al, tree->root);
   1.139 -    alfree(al, tree);
   1.140 -}
   1.141 -
   1.142 -static void ucx_avl_free_content_node(UcxAllocator *al, UcxAVLNode *node,
   1.143 -        ucx_destructor destr) {
   1.144 -    if (node) {
   1.145 -        ucx_avl_free_content_node(al, node->left, destr);
   1.146 -        ucx_avl_free_content_node(al, node->right, destr);
   1.147 -        if (destr) {
   1.148 -            destr(node->value);
   1.149 -        } else {
   1.150 -            alfree(al, node->value);
   1.151 -        }
   1.152 -    }
   1.153 -}
   1.154 -
   1.155 -void ucx_avl_free_content(UcxAVLTree *tree, ucx_destructor destr) {
   1.156 -    ucx_avl_free_content_node(tree->allocator, tree->root, destr);
   1.157 -}
   1.158 -
   1.159 -UcxAVLNode *ucx_avl_get_node(UcxAVLTree *tree, intptr_t key) {
   1.160 -    UcxAVLNode *n = tree->root;
   1.161 -    int cmpresult;
   1.162 -    while (n && (cmpresult = tree->cmpfunc(
   1.163 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   1.164 -        n = cmpresult > 0 ? n->right : n->left;
   1.165 -    }
   1.166 -    return n;
   1.167 -}
   1.168 -
   1.169 -void *ucx_avl_get(UcxAVLTree *tree, intptr_t key) {
   1.170 -    UcxAVLNode *n = ucx_avl_get_node(tree, key);
   1.171 -    return n ? n->value : NULL;
   1.172 -}
   1.173 -
   1.174 -UcxAVLNode *ucx_avl_find_node(UcxAVLTree *tree, intptr_t key,
   1.175 -        distance_func dfnc, int mode) {
   1.176 -    UcxAVLNode *n = tree->root;
   1.177 -    UcxAVLNode *closest = NULL;
   1.178 -
   1.179 -    intmax_t cmpresult;
   1.180 -    intmax_t closest_dist;
   1.181 -    closest_dist = mode == UCX_AVL_FIND_LOWER_BOUNDED ? INTMAX_MIN : INTMAX_MAX;
   1.182 -    
   1.183 -    while (n && (cmpresult = dfnc(
   1.184 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   1.185 -        if (mode == UCX_AVL_FIND_CLOSEST) {
   1.186 -            intmax_t dist = cmpresult;
   1.187 -            if (dist < 0) dist *= -1;
   1.188 -            if (dist < closest_dist) {
   1.189 -                closest_dist = dist;
   1.190 -                closest = n;
   1.191 -            }
   1.192 -        } else if (mode == UCX_AVL_FIND_LOWER_BOUNDED && cmpresult <= 0) {
   1.193 -            if (cmpresult > closest_dist) {
   1.194 -                closest_dist = cmpresult;
   1.195 -                closest = n;
   1.196 -            }
   1.197 -        } else if (mode == UCX_AVL_FIND_UPPER_BOUNDED && cmpresult >= 0) {
   1.198 -            if (cmpresult < closest_dist) {
   1.199 -                closest_dist = cmpresult;
   1.200 -                closest = n;
   1.201 -            }
   1.202 -        }
   1.203 -        n = cmpresult > 0 ? n->right : n->left;
   1.204 -    }
   1.205 -    return n ? n : closest;
   1.206 -}
   1.207 -
   1.208 -void *ucx_avl_find(UcxAVLTree *tree, intptr_t key,
   1.209 -        distance_func dfnc, int mode) {
   1.210 -    UcxAVLNode *n = ucx_avl_find_node(tree, key, dfnc, mode);
   1.211 -    return n ? n->value : NULL;
   1.212 -}
   1.213 -
   1.214 -int ucx_avl_put(UcxAVLTree *tree, intptr_t key, void *value) {
   1.215 -    return ucx_avl_put_s(tree, key, value, NULL);
   1.216 -}
   1.217 -
   1.218 -int ucx_avl_put_s(UcxAVLTree *tree, intptr_t key, void *value,
   1.219 -        void **oldvalue) {
   1.220 -    if (tree->root) {
   1.221 -        UcxAVLNode *n = tree->root;
   1.222 -        int cmpresult;
   1.223 -        while ((cmpresult = tree->cmpfunc(
   1.224 -                ptrcast(key), ptrcast(n->key), tree->userdata))) {
   1.225 -            UcxAVLNode *m = cmpresult > 0 ? n->right : n->left;
   1.226 -            if (m) {
   1.227 -                n = m;
   1.228 -            } else {
   1.229 -                break;
   1.230 -            }
   1.231 -        }
   1.232 -
   1.233 -        if (cmpresult) {
   1.234 -            UcxAVLNode* e = alloc_node(tree->allocator);
   1.235 -            if (e) {
   1.236 -                e->key = key; e->value = value; e->height = 1;
   1.237 -                e->parent = e->left = e->right = NULL;
   1.238 -                ucx_avl_connect(tree, n, e, 0);
   1.239 -                ucx_avl_balance(tree, n);
   1.240 -                return 0;
   1.241 -            } else {
   1.242 -                return 1;
   1.243 -            }
   1.244 -        } else {
   1.245 -            if (oldvalue) {
   1.246 -                *oldvalue = n->value;
   1.247 -            }
   1.248 -            n->value = value;
   1.249 -            return 0;
   1.250 -        }
   1.251 -    } else {
   1.252 -        tree->root = alloc_node(tree->allocator);
   1.253 -        if (tree->root) {
   1.254 -            tree->root->key = key; tree->root->value = value;
   1.255 -            tree->root->height = 1;
   1.256 -            tree->root->parent = tree->root->left = tree->root->right = NULL;
   1.257 -            
   1.258 -            if (oldvalue) {
   1.259 -                *oldvalue = NULL;
   1.260 -            }
   1.261 -            
   1.262 -            return 0;
   1.263 -        } else {
   1.264 -            return 1;
   1.265 -        }
   1.266 -    }
   1.267 -}
   1.268 -
   1.269 -int ucx_avl_remove(UcxAVLTree *tree, intptr_t key) {
   1.270 -    return ucx_avl_remove_s(tree, key, NULL, NULL);
   1.271 -}
   1.272 -    
   1.273 -int ucx_avl_remove_node(UcxAVLTree *tree, UcxAVLNode *node) {
   1.274 -    return ucx_avl_remove_s(tree, node->key, NULL, NULL);
   1.275 -}
   1.276 -
   1.277 -int ucx_avl_remove_s(UcxAVLTree *tree, intptr_t key,
   1.278 -        intptr_t *oldkey, void **oldvalue) {
   1.279 -    
   1.280 -    UcxAVLNode *n = tree->root;
   1.281 -    int cmpresult;
   1.282 -    while (n && (cmpresult = tree->cmpfunc(
   1.283 -            ptrcast(key), ptrcast(n->key), tree->userdata))) {
   1.284 -        n = cmpresult > 0 ? n->right : n->left;
   1.285 -    }
   1.286 -    if (n) {
   1.287 -        if (oldkey) {
   1.288 -            *oldkey = n->key;
   1.289 -        }
   1.290 -        if (oldvalue) {
   1.291 -            *oldvalue = n->value;
   1.292 -        }
   1.293 -        
   1.294 -        UcxAVLNode *p = n->parent;
   1.295 -        if (n->left && n->right) {
   1.296 -            UcxAVLNode *s = n->right;
   1.297 -            while (s->left) {
   1.298 -                s = s->left;
   1.299 -            }
   1.300 -            ucx_avl_connect(tree, s->parent, s->right, s->key);
   1.301 -            n->key = s->key; n->value = s->value;
   1.302 -            p = s->parent;
   1.303 -            alfree(tree->allocator, s);
   1.304 -        } else {
   1.305 -            if (p) {
   1.306 -                ucx_avl_connect(tree, p, n->right ? n->right:n->left, n->key);
   1.307 -            } else {
   1.308 -                tree->root = n->right ? n->right : n->left;
   1.309 -                if (tree->root) {
   1.310 -                    tree->root->parent = NULL;
   1.311 -                }
   1.312 -            }
   1.313 -            alfree(tree->allocator, n);
   1.314 -        }
   1.315 -
   1.316 -        if (p) {
   1.317 -            ucx_avl_balance(tree, p);
   1.318 -        }
   1.319 -        
   1.320 -        return 0;
   1.321 -    } else {
   1.322 -        return 1;
   1.323 -    }
   1.324 -}
   1.325 -
   1.326 -static size_t ucx_avl_countn(UcxAVLNode *node) {
   1.327 -    if (node) {
   1.328 -        return 1 + ucx_avl_countn(node->left) + ucx_avl_countn(node->right);
   1.329 -    } else {
   1.330 -        return 0;
   1.331 -    }
   1.332 -}
   1.333 -
   1.334 -size_t ucx_avl_count(UcxAVLTree *tree) {
   1.335 -    return ucx_avl_countn(tree->root);
   1.336 -}
   1.337 -
   1.338 -UcxAVLNode* ucx_avl_pred(UcxAVLNode* node) {
   1.339 -    if (node->left) {
   1.340 -        UcxAVLNode* n = node->left;
   1.341 -        while (n->right) {
   1.342 -            n = n->right;
   1.343 -        }
   1.344 -        return n;
   1.345 -    } else {
   1.346 -        UcxAVLNode* n = node;
   1.347 -        while (n->parent) {
   1.348 -            if (n->parent->right == n) {
   1.349 -                return n->parent;
   1.350 -            } else {
   1.351 -                n = n->parent;
   1.352 -            }
   1.353 -        }
   1.354 -        return NULL;
   1.355 -    }
   1.356 -}
   1.357 -
   1.358 -UcxAVLNode* ucx_avl_succ(UcxAVLNode* node) {
   1.359 -    if (node->right) {
   1.360 -        UcxAVLNode* n = node->right;
   1.361 -        while (n->left) {
   1.362 -            n = n->left;
   1.363 -        }
   1.364 -        return n;
   1.365 -    } else {
   1.366 -        UcxAVLNode* n = node;
   1.367 -        while (n->parent) {
   1.368 -            if (n->parent->left == n) {
   1.369 -                return n->parent;
   1.370 -            } else {
   1.371 -                n = n->parent;
   1.372 -            }
   1.373 -        }
   1.374 -        return NULL;
   1.375 -    }
   1.376 -}

mercurial