2015-03-16 02:02:45 +00:00
|
|
|
#include "kdef.h"
|
2015-03-07 07:06:33 +00:00
|
|
|
#include "mm.h"
|
2015-03-16 02:02:45 +00:00
|
|
|
#include "avl_tree.h"
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-01 09:11:58 +00:00
|
|
|
#define MAX(a, b) (((a) > (b) ? (a) : (b)))
|
|
|
|
|
|
|
|
// internal
|
2015-03-17 07:21:42 +00:00
|
|
|
int NATIVE64 _avl_tree_get_height(avl_tree_node *node)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-01 09:11:58 +00:00
|
|
|
return node == NULL ? -1 : node->height;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
int NATIVE64 _avl_tree_get_balance_factor(avl_tree_node *node)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-01 09:11:58 +00:00
|
|
|
if (node == NULL)
|
|
|
|
return 0;
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_get_height(node->left) - _avl_tree_get_height(node->right);
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_right_rotate(avl_tree_node *root)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_node *left_children = root->left;
|
2015-03-01 09:11:58 +00:00
|
|
|
//adjust parents first
|
|
|
|
left_children->parent = root->parent;
|
|
|
|
root->parent = left_children;
|
|
|
|
if (left_children->right != NULL)
|
|
|
|
left_children->right->parent = root;
|
|
|
|
//perform rotation
|
|
|
|
root->left = root->left->right;
|
|
|
|
left_children->right = root;
|
|
|
|
//adjust height
|
2015-03-17 07:21:42 +00:00
|
|
|
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1;
|
|
|
|
left_children->height = MAX(_avl_tree_get_height(left_children->left), _avl_tree_get_height(left_children->right)) + 1;
|
2015-03-01 09:11:58 +00:00
|
|
|
return left_children;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_left_rotate(avl_tree_node *root)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_node *right_children = root->right;
|
2015-03-01 09:11:58 +00:00
|
|
|
//adjust parents
|
|
|
|
right_children->parent = root->parent;
|
|
|
|
root->parent = right_children;
|
|
|
|
if (right_children->left != NULL)
|
|
|
|
right_children->left->parent = root;
|
|
|
|
//perform rotation
|
|
|
|
root->right = root->right->left;
|
|
|
|
right_children->left = root;
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1;
|
|
|
|
right_children->height = MAX(_avl_tree_get_height(right_children->left), _avl_tree_get_height(right_children->right)) + 1;
|
2015-03-01 09:11:58 +00:00
|
|
|
return right_children;
|
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_balance_node(avl_tree_node *node)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
const int bf = _avl_tree_get_balance_factor(node);
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-01 09:11:58 +00:00
|
|
|
if (bf > 1)
|
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
const int left_bf = _avl_tree_get_balance_factor(node->left);
|
2015-03-01 09:11:58 +00:00
|
|
|
if (left_bf >= 0)
|
|
|
|
//left left
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_right_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//left right
|
2015-03-17 07:21:42 +00:00
|
|
|
node->left = _avl_tree_left_rotate(node->left);
|
|
|
|
return _avl_tree_right_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bf < -1)
|
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
const int right_bf = _avl_tree_get_balance_factor(node->right);
|
2015-03-01 09:11:58 +00:00
|
|
|
if (right_bf <= 0)
|
|
|
|
{
|
|
|
|
// right right
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_left_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// right left
|
2015-03-17 07:21:42 +00:00
|
|
|
node->right = _avl_tree_right_rotate(node->right);
|
|
|
|
return _avl_tree_left_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return node;
|
2015-02-21 10:47:24 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2015-03-16 02:02:45 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void * NATIVE64 _avl_tree_search(avl_tree_node *root, void *data, int(*compare)(void *, void *))
|
2015-03-16 02:02:45 +00:00
|
|
|
{
|
|
|
|
if(root == NULL)
|
|
|
|
return NULL;
|
|
|
|
const int comp = compare(root->data, data);
|
|
|
|
if (comp < 0)
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_search(root->right, data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
else if (comp == 0)
|
|
|
|
return root->data;
|
|
|
|
else
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_search(root->left, data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void * NATIVE64 avl_tree_search(avl_tree *root, void *data, int(*compare)(void *, void *))
|
2015-03-16 02:02:45 +00:00
|
|
|
{
|
|
|
|
if(root == NULL || data == NULL)
|
|
|
|
return NULL;
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_search(root->root, data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_create_node()
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_node *tree = (avl_tree_node *) (kmalloc(sizeof(avl_tree_node)));
|
2015-03-01 09:11:58 +00:00
|
|
|
tree->parent = NULL;
|
|
|
|
tree->data = NULL;
|
|
|
|
tree->right = NULL;
|
|
|
|
tree->left = NULL;
|
|
|
|
tree->height = 0;
|
|
|
|
return tree;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_insert(avl_tree_node *root, void *data, int(*compare)(void *, void *), avl_tree_node *parent)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-01 09:11:58 +00:00
|
|
|
if (data == NULL)
|
|
|
|
return root;
|
|
|
|
if (root == NULL)
|
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node *tree = _avl_tree_create_node();
|
2015-03-01 09:11:58 +00:00
|
|
|
tree->data = data;
|
|
|
|
tree->parent = parent;
|
|
|
|
return tree;
|
|
|
|
}
|
|
|
|
|
|
|
|
const int comp = compare(root->data, data);
|
|
|
|
if (comp < 0)
|
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
root->right = _avl_tree_insert(root->right, data, compare, root);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
else if (comp == 0)
|
|
|
|
return root;
|
2015-02-21 10:47:24 +00:00
|
|
|
else
|
2015-03-17 07:21:42 +00:00
|
|
|
root->left = _avl_tree_insert(root->left, data, compare, root);
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1;
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
return _avl_tree_balance_node(root);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 avl_tree_insert(avl_tree *tree, void *data, int (*compare)(void *, void *))
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if(tree != NULL && data != NULL && compare != NULL)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
if(avl_tree_search(tree, data, compare) == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
tree->root = _avl_tree_insert(tree->root, data, compare, NULL);
|
2015-03-16 02:02:45 +00:00
|
|
|
tree->size++;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_delete(avl_tree_node *root, void *data, int (*compare)(void *, void *))
|
2015-03-16 02:02:45 +00:00
|
|
|
{
|
|
|
|
if (root == NULL || data == NULL)
|
|
|
|
return root;
|
|
|
|
const int comp = compare(root->data, data);
|
|
|
|
if (comp < 0)
|
2015-03-17 07:21:42 +00:00
|
|
|
root->right = _avl_tree_delete(root->right, data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
else if(comp > 0)
|
2015-03-17 07:21:42 +00:00
|
|
|
root->left = _avl_tree_delete(root->left, data, compare);
|
2015-03-01 09:11:58 +00:00
|
|
|
else
|
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
// node with only one child or no child
|
|
|
|
if( (root->left == NULL) || (root->right == NULL) )
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_node *child = root->left != NULL ? root->left : root->right;
|
|
|
|
|
|
|
|
if(child == NULL)
|
|
|
|
{ // 0 child
|
|
|
|
//free(root);
|
|
|
|
root = NULL;
|
|
|
|
}
|
|
|
|
else // 1 child
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
//copy content of temp to root except for the parent
|
|
|
|
root->left = child->left;
|
|
|
|
root->right = child->right;
|
|
|
|
root->data = child->data;
|
|
|
|
root->height = child->height;
|
|
|
|
//free(child);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
// node with two children: Get the inorder successor (smallest
|
|
|
|
// in the right subtree)
|
|
|
|
|
|
|
|
avl_tree_node * temp = root->right;
|
|
|
|
while(temp->left != NULL)
|
|
|
|
temp = temp->left;
|
|
|
|
|
|
|
|
// Copy the inorder successor's data to this node
|
|
|
|
root->data = temp->data;
|
|
|
|
|
|
|
|
// Delete the inorder successor
|
2015-03-17 07:21:42 +00:00
|
|
|
root->right = _avl_tree_delete(root->right, temp->data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
if (root == NULL)
|
|
|
|
return root;
|
2015-03-17 07:21:42 +00:00
|
|
|
root->height = MAX(_avl_tree_get_height(root->left), _avl_tree_get_height(root->right)) + 1;
|
|
|
|
root = _avl_tree_balance_node(root);
|
2015-03-16 02:02:45 +00:00
|
|
|
return root;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 avl_tree_delete(avl_tree *tree, void *data, int (*compare)(void *, void *))
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if(tree != NULL && data != NULL && compare != NULL && tree->size != 0)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
if(avl_tree_search(tree, data, compare) != NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
tree->root = _avl_tree_delete(tree->root, data, compare);
|
2015-03-16 02:02:45 +00:00
|
|
|
tree->size--;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
return;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 _avl_tree_free(avl_tree_node *root, void (*delete_data)(void *))
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if(root != NULL)
|
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
_avl_tree_free(root->left, delete_data);
|
|
|
|
_avl_tree_free(root->right, delete_data);
|
2015-03-16 02:02:45 +00:00
|
|
|
if (delete_data != NULL)
|
|
|
|
delete_data(root->data);
|
|
|
|
}
|
|
|
|
return;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 avl_tree_free(avl_tree *tree, void (*delete_data)(void *))
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if(tree != NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-17 07:21:42 +00:00
|
|
|
_avl_tree_free(tree->root, delete_data);
|
2015-03-16 02:02:45 +00:00
|
|
|
kfree(tree);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
return;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree * NATIVE64 avl_tree_create()
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree* new_tree = kmalloc(sizeof(avl_tree));
|
|
|
|
new_tree->root = NULL;
|
|
|
|
new_tree->size = 0;
|
|
|
|
return new_tree;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-16 02:02:45 +00:00
|
|
|
|
|
|
|
//iterator
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_node * NATIVE64 _avl_tree_smallest(avl_tree_node *root)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
|
|
|
if (root == NULL)
|
|
|
|
return NULL;
|
|
|
|
while (root->left != NULL)
|
|
|
|
root = root->left;
|
|
|
|
return root;
|
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
avl_tree_iterator* NATIVE64 avl_tree_create_iterator(avl_tree *tree)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if(tree == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return NULL;
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_iterator* it = (avl_tree_iterator*)kmalloc(sizeof(avl_tree_iterator));
|
2015-03-17 07:21:42 +00:00
|
|
|
it->current = _avl_tree_smallest(tree->root);
|
2015-03-16 02:02:45 +00:00
|
|
|
return it;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 avl_tree_next(avl_tree_iterator *it)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if (it == NULL || it->current == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return;
|
2015-03-16 02:02:45 +00:00
|
|
|
avl_tree_node* root = it->current;
|
|
|
|
if (root->right != NULL)
|
|
|
|
{
|
|
|
|
root = root->right;
|
|
|
|
while (root->left != NULL)
|
|
|
|
{
|
|
|
|
root = root->left;
|
|
|
|
}
|
|
|
|
it->current = root;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (root->parent != NULL)
|
|
|
|
{
|
|
|
|
if (root->parent->left == root)
|
|
|
|
{
|
|
|
|
it->current = root->parent;
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
root = root->parent;
|
|
|
|
}
|
|
|
|
it->current = NULL;
|
|
|
|
return;
|
|
|
|
}
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
void NATIVE64 avl_tree_prev(avl_tree_iterator *it)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if (it == NULL || it->current == NULL)
|
|
|
|
return;
|
|
|
|
avl_tree_node* root = it->current;
|
|
|
|
if (root->left != NULL)
|
|
|
|
{
|
|
|
|
root = root->left;
|
|
|
|
while (root->right != NULL)
|
|
|
|
{
|
|
|
|
root = root->right;
|
|
|
|
}
|
|
|
|
it->current = root;
|
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
else
|
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
while (root->parent != NULL)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if (root->parent->right == root)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
it->current = root->parent;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
root = root->parent;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-16 02:02:45 +00:00
|
|
|
it->current = NULL;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-01 09:11:58 +00:00
|
|
|
// TESTS
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
int NATIVE64 avl_tree_test_calculate_height(avl_tree_node *tree)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if (tree == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return -1;
|
2015-03-17 07:21:42 +00:00
|
|
|
return MAX(avl_tree_test_calculate_height(tree->left), avl_tree_test_calculate_height(tree->right)) + 1;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-17 07:21:42 +00:00
|
|
|
int NATIVE64 avl_tree_test(avl_tree_node *tree)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-16 02:02:45 +00:00
|
|
|
if (tree == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return 1;
|
2015-03-17 07:21:42 +00:00
|
|
|
if (_avl_tree_get_balance_factor(tree) < -1 || _avl_tree_get_balance_factor(tree) > 1 || avl_tree_test_calculate_height(tree) != tree->height)
|
2015-03-01 09:11:58 +00:00
|
|
|
return 0;
|
2015-03-17 07:21:42 +00:00
|
|
|
return avl_tree_test(tree->left) && avl_tree_test(tree->right);
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-01 09:11:58 +00:00
|
|
|
|