actube/src/cw/mavl_add.c

198 lines
3.3 KiB
C

#include "mavl.h"
static struct mavlnode *mavlnode_create(const union mavldata *data)
{
struct mavlnode *n = malloc(sizeof(struct mavlnode));
if (!n)
return NULL;
n->left = n->right = 0;
n->bal = 0;
n->data = *data;
return n;
}
static int mavl_add0(struct mavl *t, struct mavlnode **parent, union mavldata ** data)
{
struct mavlnode *tmp;
struct mavlnode *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 = mavl_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;
}
}
return bal;
}
/* n->left is 0 */
n->left = mavlnode_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 = mavl_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;
}
}
return bal;
}
/* n->right is 0 */
n->right = mavlnode_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
*
* @param t mavl
* @param data pointer to element
*
* @return A pointer to the element in the tree. If teh returned pointer
* equals to the pointer given in the data argument, the element has already
* been in the tree. If the function returns NULL, there was en error, e.g.
* no memory left. Consult therefore errno.
*
* @example mavl_add_example.c
*/
union mavldata *mavl_add(struct mavl *t, union mavldata *data)
{
union mavldata * d;
int rc;
if (t->root == NULL) {
t->root = mavlnode_create(data);
if (t->root)
t->count++;
/* return &t->root->data; */
return data;
}
d = data;
rc = mavl_add0(t, &t->root, &d);
if (rc > 3)
return NULL;
return d;
}