/* This file is part of libcapwap. libcapwap is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. libcapwap is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Foobar. If not, see . */ /** * @file * @brief Yet another AVL tree implementation */ #include #include #include "avltree.h" /** * Create an AVL tree * @param cmp pointer compare function * @param del pointer to delete function which is called when an element will be deletet * @return pointer to an #avltree struct */ struct avltree *avltree_create(int (*cmp) (const void *, const void *), void (*del) (void *)) { struct avltree *t = malloc(sizeof(struct avltree)); if (!t) return NULL; t->root = 0; t->count = 0; t->cmp = cmp; t->del = del; return t; } struct avlnode *avlnode_create(void *data) { struct avlnode *n = malloc(sizeof(struct avlnode)); if (!n) return NULL; n->left = n->right = 0; n->bal = 0; n->data = data; return n; } void avlnode_destroy(struct avltree *t, struct avlnode *n) { if (t->del) { t->del(n->data); } free(n); t->count--; } static int avltree_add0(struct avltree *t, struct avlnode **parent, void **data) { // struct avlnode * rn; struct avlnode *tmp; struct avlnode *n = *parent; int rc = t->cmp(*data, n->data); int bal; if (rc == 0) { *data = n->data; return 2; } if (rc < 0) { if (n->left) { bal = avltree_add0(t, &n->left, data); if (bal > 1) return bal; n->bal -= bal; if (n->bal == 0) return 0; if (n->bal == -2) { if (n->left->bal == -1) { n->bal = 0; n->left->bal = 0; *parent = n->left; tmp = n->left->right; n->left->right = n; n->left = tmp; return 0; } if (n->left->bal == 1) { *parent = n->left->right; if ((*parent)->bal == 1) { n->bal = 0; n->left->bal = -1; } else if ((*parent)->bal == -1) { n->bal = 1; n->left->bal = 0; } else { n->bal = 0; n->left->bal = 0; } (*parent)->bal = 0; n->left->right = (*parent)->left; (*parent)->left = n->left; tmp = (*parent)->right; (*parent)->right = n; n->left = tmp; return 0; } //printf("!!!!left bal = %i\n",n->left->bal); //exit(0); } return bal; } /* n->left is 0 */ n->left = avlnode_create(*data); if (!n->left) return 3; t->count++; if (n->right == 0) { n->bal = -1; return 1; } n->bal = 0; return 0; } else { if (n->right) { bal = avltree_add0(t, &n->right, data); if (bal > 1) return bal; n->bal += bal; if (n->bal == 0) return 0; if (n->bal == 2) { if (n->right->bal == 1) { n->bal = 0; n->right->bal = 0; *parent = n->right; tmp = n->right->left; n->right->left = n; n->right = tmp; return 0; } else if (n->right->bal == -1) { *parent = n->right->left; if ((*parent)->bal == -1) { n->bal = 0; n->right->bal = 1; } else if ((*parent)->bal == 1) { n->bal = -1; n->right->bal = 0; } else { n->bal = 0; n->right->bal = 0; } (*parent)->bal = 0; n->right->left = (*parent)->right; (*parent)->right = n->right; tmp = (*parent)->left; (*parent)->left = n; n->right = tmp; return 0; } //printf("!!!!iright bal = %i\n",n->left->bal); //exit(0); } return bal; } /* n->right is 0 */ n->right = avlnode_create(*data); if (!n->right) return 3; t->count++; if (n->left == 0) { n->bal = 1; return 1; } n->bal = 0; return 0; } } /** * Add an element to an AVL tree * @t avltree * @data pointer to element * @return added alement or NULL if error. */ void *avltree_add(struct avltree *t, void *data) { if (t->root == 0) { t->root = avlnode_create(data); if (t->root) t->count++; return t->root->data; } void *d = data; int rc = avltree_add0(t, &t->root, &d); if (rc > 3) return NULL; return d; } static void rot_l(struct avlnode *n, struct avlnode **parent) { struct avlnode *tmp; *parent = n->right; tmp = n->right->left; n->right->left = n; n->right = tmp; } static void rot_r(struct avlnode *n, struct avlnode **parent) { struct avlnode *tmp; *parent = n->left; tmp = n->left->right; n->left->right = n; n->left = tmp; } /* * Delete the node with the highest value * returns the rebalancing factor */ /* static int avltree_delete_hi(struct avlnode **parent, void **data) { struct avlnode * n = *parent; if(n->right!=0){ int bal = avltree_delete_hi(&n->right,data); n->bal-=bal; if (n->bal==-2){ // if (rotate_r(n,parent)) // return 0; } return bal; } *parent=n->left; *data = n->data; if (n->left){ free(n); return 0; } free(n); return 1; } */ //struct avltree * trrr; static void rot_rl(struct avlnode *n, struct avlnode **parent) { struct avlnode *tmp; *parent = n->right->left; n->right->left = (*parent)->right; (*parent)->right = n->right; tmp = (*parent)->left; (*parent)->left = n; n->right = tmp; } static void rot_lr(struct avlnode *n, struct avlnode **parent) { struct avlnode *tmp; *parent = n->left->right; n->left->right = (*parent)->left; (*parent)->left = n->left; tmp = (*parent)->right; (*parent)->right = n; n->left = tmp; } static int adj_bal_l(struct avlnode *n, struct avlnode **parent) { if (n->right->bal == 1) { n->bal = 0; n->right->bal = 0; rot_l(n, parent); return 1; } else if (n->right->bal == 0) { n->bal = 1; n->right->bal = -1; rot_l(n, parent); return 0; } else if (n->right->bal == -1) { // int rb; n->bal = 0; n->right->bal = 0; // rb = n->right->left->bal; n->right->left->bal = 0; rot_rl(n, parent); return 1; } // printf("adj bal l not handled \n"); // exit(0); return -11; /* that should never happen */ } int adj_bal_r(struct avlnode *n, struct avlnode **parent) { if (n->left->bal == -1) { n->bal = 0; n->left->bal = 0; rot_r(n, parent); return 1; } else if (n->left->bal == 0) { n->bal = -1; n->left->bal = 1; rot_r(n, parent); return 0; } else if (n->left->bal == 1) { // int rb; n->bal = 0; n->left->bal = 0; // rb = n->left->right->bal; n->left->right->bal = 0; rot_lr(n, parent); return 1; } // printf("adj bal li left not handled \n"); // exit(0); return -11; /* that should never happen */ } static int avltree_del_lo(struct avlnode **parent, void **data) { struct avlnode *n = *parent; if (n->left != 0) { int bal = avltree_del_lo(&n->left, data); n->bal += bal; if (n->bal == 1) { return 0; } if (n->bal != 2) return bal; adj_bal_l(n, parent); return 0; } /* found the lowest element */ *parent = n->right; *data = n->data; free(n); return 1; if (n->right) { free(n); return 1; } free(n); return 1; } int avltree_del0(struct avltree *t, struct avlnode **parent, void **data) { struct avlnode *n = *parent; int rc; int bal; rc = t->cmp(*data, n->data); if (rc == 0) { if (n->right == 0 && n->left == 0) { *parent = 0; avlnode_destroy(t, n); return 1; } if (n->right && n->left == 0) { *parent = n->right; avlnode_destroy(t, n); return 1; } if (n->left && n->right == 0) { avlnode_destroy(t, n); *parent = n->left; return 1; } /* node has two childs */ if (t->del) { t->del(n->data); } t->count--; bal = avltree_del_lo(&n->right, &n->data); n->bal -= bal; if (n->bal == -1) return 0; if (n->bal != -2) return bal; return adj_bal_r(n, parent); } if (rc < 0) { if (n->left) { bal = avltree_del0(t, &n->left, data); if (bal == 2) return 2; n->bal += bal; if (n->bal == 1) return 0; if (n->bal != 2) return bal; return adj_bal_l(n, parent); } return 2; /* not found */ } else { /* rc must be > 0 */ if (n->right) { bal = avltree_del0(t, &n->right, data); if (bal == 2) return 2; n->bal -= bal; if (n->bal == -1) return 0; if (n->bal != -2) return bal; return adj_bal_r(n, parent); } return 2; /* not found */ } } void *avltree_del(struct avltree *t, void *data) { if (!t->root) return NULL; void *d = data; int rc = avltree_del0(t, &t->root, &d); if (rc == 2) return NULL; return data; } /* static int cmp(const void *k1,const void *k2) { int x1 = *((int*)k1); int x2 = *((int*)k2); return x1-x2; } */ //int data[]={10,37,60,10,5,35,36,26,3,11,18}; //int data[] = {100,50,75}; //int data[]={100,200,150,300,400}; //int data[]={100,200,150,170,470}; //int data[]={10,20,15,17,47,50,60,70,80}; //int data[]={9,8,7,6,5,4,3,2,1,0}; //int data[]={10,37,60,10,5,35,19,26,3,11,18}; //int data[]={0,11,14,33,37,20}; //int data[]={1,2,3,4,5,6,7,8,9,10,11,12,13,14,15}; //int data[]={1,4,3,7,5,6,7,8,9,10}; //int data[]={11,4,5,6,3,4,3,2,1,0}; //int data[]={20,16,10,11,5,4,3,2,1,0}; /* struct avlnode * ar[10000]; int tpw = 80; static void print_tree0(struct avlnode * n,int d,int l,int r) { int pos = l+(r-l)/2; ar[d*tpw+pos]=n; if (n->right) print_tree0(n->right,d+1,l+(r-l)/2,r); if(n->left) print_tree0(n->left,d+1,l,r-(r-l)/2); } void avltree_print(struct avlnode * n ) { int y; int i=0; for(i=0; i<10000; i++) ar[i]=0; if (n==0){ printf("Empty Tree\n"); return ; } print_tree0(n,0,0,tpw); for (i=0; i<10; i++) { for (y=0; ydata),r->bal); } else{ printf("."); } } printf("\n"); } } void walk(struct avlnode *n) { if (n == 0) return; walk(n->left); int x = *((int*)(n->data)); printf("VAL: %i\n",x); walk(n->right); // x = *((int*)(n->data)); // printf("VALR: %i\n",x); } */ /* void avltree_destroy(struct avltree *t) { avltree_del_all(t); free (t); } */ //#include /* //int data[]={5,1,9,7,0,10,8,0,4,3}; //int data[]={50,10,90,70,00,100,80,00,40,30,1,2,3}; int data[]={10,20,30,45,1,50,11,51,60,70,80,90,99,25,50,10,90,70,00,100,80,00,40,30,1,2,3}; int main() { struct avltree *t = avltree_create(cmp,0); trrr=t; printf("T: %p\n",t); srand(time(NULL)); int i=0; for (i=0; i<6; i++) { int r = rand()%0x3f; // % 0xiff; // int r = rand(); //%0x3f; // % 0xiff; // r = data[7-i]; r = data[i]; int * dr = malloc(sizeof(int)); *dr = r; printf("Insert %i\n",*dr); void * d = avltree_insert(t,dr); printf("After insert %i\n",r); print_tree(t->root); if (d!=dr){ // printf("exists\n"); } } printf("Here it is\n"); print_tree(t->root); // walk(t->root); void * da; int x = 110; // void * drc = avltree_delete(t,&x); avltree_delete_all(t); // printf("Delete 110 rc = %p\n",drc); print_tree(t->root); printf("Count: %i\n",t->count); return 0; } */