/***************************************************************************
*
* Copyright 2013 by Sean Conner.
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation; either version 3 of the License, or (at your
* option) any later version.
*
* This library 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 Lesser General Public
* License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this library; if not, see .
*
* Comments, questions and criticisms can be sent to: sean@conman.org
*
*************************************************************************/
#include
#include
#include "tree.h"
/*************************************************************************/
static int tree_delta (tree__s *);
static tree__s *tree_rotl (tree__s *);
static tree__s *tree_rotr (tree__s *);
static tree__s *tree_balance (tree__s *);
/*************************************************************************/
static int tree_delta(tree__s *self)
{
assert(self != NULL);
return (self->left ? self->left->height : 0)
- (self->right ? self->right->height : 0);
}
/*************************************************************************/
static tree__s *tree_rotl(tree__s *self)
{
assert(self != NULL);
tree__s *r = self->right;
self->right = r->left;
r->left = tree_balance(self);
return tree_balance(r);
}
/*************************************************************************/
static tree__s *tree_rotr(tree__s *self)
{
assert(self != NULL);
tree__s *l = self->left;
self->left = l->right;
l->right = tree_balance(self);
return tree_balance(l);
}
/*************************************************************************/
static tree__s *tree_balance(tree__s *self)
{
assert(self != NULL);
int delta = tree_delta(self);
if (delta < -1)
{
if (tree_delta(self->right) > 0)
self->right = tree_rotr(self->right);
return tree_rotl(self);
}
else if (delta > 1)
{
if (tree_delta(self->left) < 0)
self->left = tree_rotl(self->left);
return tree_rotr(self);
}
self->height = 0;
if (self->left && (self->left->height > self->height))
self->height = self->left->height;
if (self->right && (self->right->height > self->height))
self->height = self->right->height;
self->height += 1;
return self;
}
/*************************************************************************/
static tree__s *tree_move_right(tree__s *restrict self,tree__s *restrict rhs)
{
if (self == NULL)
return rhs;
self->right = tree_move_right(self->right,rhs);
return tree_balance(self);
}
/*************************************************************************/
tree__s *tree_insert(
tree__s *restrict self,
tree__s *restrict item,
int (*compare)(void const *restrict,void const *restrict)
)
{
int rc;
if (self == NULL)
return item;
rc = (*compare)(item,self);
if (rc < 0)
self->left = tree_insert(self->left,item,compare);
else
self->right = tree_insert(self->right,item,compare);
return tree_balance(self);
}
/*************************************************************************/
tree__s *tree_find(
tree__s *self,
void const *item,
int (*compare)(void const *restrict,void const *restrict)
)
{
int rc;
if (self == NULL)
return NULL;
rc = (*compare)(item,self);
if (rc < 0)
return tree_find(self->left,item,compare);
else if (rc == 0)
return self;
else
return tree_find(self->right,item,compare);
}
/*************************************************************************/
tree__s *tree_remove(
tree__s *self,
void const *item,
int (*compare)(void const *restrict,void const *restrict),
tree__s **remove
)
{
int rc;
if (self == NULL)
return NULL;
rc = (*compare)(item,self);
if (rc < 0)
self->left = tree_remove(self->left,item,compare,remove);
else if (rc == 0)
{
if (remove != NULL)
*remove = self;
tree__s *tmp = tree_move_right(self->left,self->right);
return tmp;
}
else
self->right = tree_remove(self->right,item,compare,remove);
return tree_balance(self);
}
/*************************************************************************/
.