2018-03-25 08:34:32 +02:00
|
|
|
/**
|
|
|
|
* @file
|
|
|
|
* @brief Implementation of mavl_add
|
|
|
|
*/
|
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
#include "mavl.h"
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
static struct mavlnode *mavlnode_create ( struct mavl *t, const void *data )
|
2015-04-17 07:45:02 +02:00
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
struct mavlnode *n = malloc ( sizeof ( struct mavlnode ) + t->data_size );
|
|
|
|
|
|
|
|
if ( !n )
|
2015-04-17 07:45:02 +02:00
|
|
|
return NULL;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
n->left = n->right = NULL;
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
/*n->data = *data;*/
|
|
|
|
memcpy ( mavlnode_dataptr ( n ), data, t->data_size );
|
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
return n;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
static int mavl_add0 ( struct mavl *t, struct mavlnode **parent, const void ** data )
|
2015-04-17 07:45:02 +02:00
|
|
|
{
|
|
|
|
struct mavlnode *tmp;
|
|
|
|
struct mavlnode *n = *parent;
|
2018-03-11 00:56:41 +01:00
|
|
|
int rc = t->cmp ( *data, mavlnode_dataptr ( n ) );
|
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
int bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( rc == 0 ) {
|
|
|
|
/* *data = &n->data;*/
|
|
|
|
|
|
|
|
/* memcpy(data,mavlnode_dataptr(n),t->data_size);*/
|
|
|
|
*data = mavlnode_dataptr ( n );
|
2015-04-17 07:45:02 +02:00
|
|
|
return 2;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( rc < 0 ) {
|
|
|
|
if ( n->left ) {
|
|
|
|
bal = mavl_add0 ( t, &n->left, data );
|
|
|
|
|
|
|
|
if ( bal > 1 )
|
2015-04-17 07:45:02 +02:00
|
|
|
return bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal -= bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->bal == 0 )
|
2015-04-17 07:45:02 +02:00
|
|
|
return 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->bal == -2 ) {
|
|
|
|
if ( n->left->bal == -1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
n->left->bal = 0;
|
|
|
|
*parent = n->left;
|
|
|
|
tmp = n->left->right;
|
|
|
|
n->left->right = n;
|
|
|
|
n->left = tmp;
|
|
|
|
return 0;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->left->bal == 1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
*parent = n->left->right;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( ( *parent )->bal == 1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
n->left->bal = -1;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
} else if ( ( *parent )->bal == -1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 1;
|
|
|
|
n->left->bal = 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
} else {
|
|
|
|
n->bal = 0;
|
|
|
|
n->left->bal = 0;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
( *parent )->bal = 0;
|
|
|
|
n->left->right = ( *parent )->left;
|
|
|
|
( *parent )->left = n->left;
|
|
|
|
tmp = ( *parent )->right;
|
|
|
|
( *parent )->right = n;
|
2015-04-17 07:45:02 +02:00
|
|
|
n->left = tmp;
|
|
|
|
return 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
return bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
/* n->left is 0 */
|
2018-03-11 00:56:41 +01:00
|
|
|
n->left = mavlnode_create ( t, *data );
|
|
|
|
*data = mavlnode_dataptr(n->left);
|
|
|
|
|
|
|
|
if ( !n->left )
|
2015-04-17 07:45:02 +02:00
|
|
|
return 3;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
t->count++;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->right == 0 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = -1;
|
|
|
|
return 1;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
return 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
} else {
|
2018-03-11 00:56:41 +01:00
|
|
|
if ( n->right ) {
|
|
|
|
bal = mavl_add0 ( t, &n->right, data );
|
|
|
|
|
|
|
|
if ( bal > 1 )
|
2015-04-17 07:45:02 +02:00
|
|
|
return bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal += bal;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->bal == 0 )
|
2015-04-17 07:45:02 +02:00
|
|
|
return 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->bal == 2 ) {
|
|
|
|
if ( n->right->bal == 1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
n->right->bal = 0;
|
|
|
|
*parent = n->right;
|
|
|
|
tmp = n->right->left;
|
|
|
|
n->right->left = n;
|
|
|
|
n->right = tmp;
|
|
|
|
return 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
} else if ( n->right->bal == -1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
*parent = n->right->left;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( ( *parent )->bal == -1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
n->right->bal = 1;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
} else if ( ( *parent )->bal == 1 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = -1;
|
|
|
|
n->right->bal = 0;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
} else {
|
|
|
|
n->bal = 0;
|
|
|
|
n->right->bal = 0;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
( *parent )->bal = 0;
|
|
|
|
n->right->left = ( *parent )->right;
|
|
|
|
( *parent )->right = n->right;
|
|
|
|
tmp = ( *parent )->left;
|
|
|
|
( *parent )->left = n;
|
2015-04-17 07:45:02 +02:00
|
|
|
n->right = tmp;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
return bal;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
/* n->right is 0 */
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
n->right = mavlnode_create ( t, *data );
|
|
|
|
*data = mavlnode_dataptr(n->right);
|
2015-04-17 07:45:02 +02:00
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( !n->right )
|
2015-04-17 07:45:02 +02:00
|
|
|
return 3;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
t->count++;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( n->left == 0 ) {
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 1;
|
|
|
|
return 1;
|
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2015-04-17 07:45:02 +02:00
|
|
|
n->bal = 0;
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
2018-03-25 08:34:32 +02:00
|
|
|
* @brief mavl add function
|
2015-04-17 07:45:02 +02:00
|
|
|
* Add an element to an AVL tree
|
2018-03-05 20:39:15 +01:00
|
|
|
* @param t mavl
|
2018-03-19 17:26:01 +01:00
|
|
|
* @param data pointer to the element to add
|
|
|
|
* @param exists pointer to an interger vairable which wil be set to 1, if
|
|
|
|
* the element to add already exists in the tree. If the element did't
|
|
|
|
* exist, the variable ist to 0.
|
2018-03-25 08:34:32 +02:00
|
|
|
|
2018-03-19 17:26:01 +01:00
|
|
|
* @return A pointer to the element in the tree. If the element was added,
|
|
|
|
* it the pointer to newly created element. If the element had already existed,
|
|
|
|
* the pointer points to the existing element. mavl_add returns thero, if
|
|
|
|
* something else went wrong. Therefore consult errno.
|
2018-03-25 08:34:32 +02:00
|
|
|
*
|
|
|
|
*
|
2015-04-17 07:45:02 +02:00
|
|
|
*/
|
2018-03-11 00:56:41 +01:00
|
|
|
void *mavl_add ( struct mavl *t, const void *data, int *exists )
|
2015-04-17 07:45:02 +02:00
|
|
|
{
|
2018-03-11 00:56:41 +01:00
|
|
|
const void * d;
|
2018-03-03 17:42:28 +01:00
|
|
|
int rc;
|
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
if ( t->root == NULL ) {
|
|
|
|
t->root = mavlnode_create ( t, data );
|
2018-03-09 07:44:17 +01:00
|
|
|
|
2018-03-11 00:56:41 +01:00
|
|
|
if ( t->root )
|
|
|
|
t->count++;
|
|
|
|
|
2018-03-09 07:44:17 +01:00
|
|
|
/* return &t->root->data; */
|
2018-03-11 00:56:41 +01:00
|
|
|
if (exists != NULL)
|
|
|
|
*exists=0;
|
|
|
|
return mavlnode_dataptr(t->root);
|
2015-04-17 07:45:02 +02:00
|
|
|
}
|
2018-03-11 00:56:41 +01:00
|
|
|
|
2018-03-03 17:42:28 +01:00
|
|
|
d = data;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
rc = mavl_add0 ( t, &t->root, &d );
|
|
|
|
|
|
|
|
if ( rc >= 3 )
|
2015-04-17 07:45:02 +02:00
|
|
|
return NULL;
|
2018-03-11 00:56:41 +01:00
|
|
|
|
|
|
|
if ( exists != NULL){
|
|
|
|
if (rc==2)
|
|
|
|
*exists=1;
|
|
|
|
else
|
|
|
|
*exists=0;
|
|
|
|
}
|
2018-03-17 19:32:44 +01:00
|
|
|
return (void*)d;
|
2015-04-17 07:45:02 +02:00
|
|
|
}
|