Massive backlog of changes
This commit is contained in:
198
src/avltree.c
Normal file
198
src/avltree.c
Normal file
@@ -0,0 +1,198 @@
|
||||
#include "avltree.h"
|
||||
#include "heap.h"
|
||||
#include "stddef.h"
|
||||
|
||||
struct avltree_t *avl_new(int key, void *value)
|
||||
{
|
||||
struct avltree_t *new_tree = kmalloc(sizeof(struct avltree_t));
|
||||
new_tree->height = 1;
|
||||
new_tree->left = new_tree->right = NULL;
|
||||
new_tree->key = key;
|
||||
new_tree->value = value;
|
||||
return new_tree;
|
||||
}
|
||||
|
||||
int avl_height(struct avltree_t *tree)
|
||||
{
|
||||
if(tree == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return tree->height;
|
||||
}
|
||||
}
|
||||
|
||||
int avl_balance(struct avltree_t *tree)
|
||||
{
|
||||
if(tree == NULL)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return avl_height(tree->left) - avl_height(tree->right);
|
||||
}
|
||||
}
|
||||
|
||||
void avl_update_height(struct avltree_t *tree)
|
||||
{
|
||||
if(tree != NULL)
|
||||
{
|
||||
tree->height = 1 + (avl_height(tree->left) > avl_height(tree->right) ? avl_height(tree->left) : avl_height(tree->right));
|
||||
}
|
||||
}
|
||||
|
||||
struct avltree_t *avl_right_rotate(struct avltree_t *y)
|
||||
{
|
||||
struct avltree_t *x = y->left;
|
||||
struct avltree_t *z = x->right;
|
||||
x->right = y;
|
||||
y->left = z;
|
||||
avl_update_height(x);
|
||||
avl_update_height(y);
|
||||
return x;
|
||||
}
|
||||
|
||||
struct avltree_t *avl_left_rotate(struct avltree_t *x)
|
||||
{
|
||||
struct avltree_t *y = x->right;
|
||||
struct avltree_t *z = y->left;
|
||||
y->left = x;
|
||||
x->right = z;
|
||||
avl_update_height(x);
|
||||
avl_update_height(y);
|
||||
return y;
|
||||
}
|
||||
|
||||
struct avltree_t *avl_insert(struct avltree_t *tree, int key, void *value)
|
||||
{
|
||||
if(tree == NULL)
|
||||
{
|
||||
return avl_new(key, value);
|
||||
}
|
||||
else if(key < tree->key)
|
||||
{
|
||||
tree->left = avl_insert(tree->left, key, value);
|
||||
}
|
||||
else if(key > tree->key)
|
||||
{
|
||||
tree->right = avl_insert(tree->right, key, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tree;
|
||||
}
|
||||
|
||||
avl_update_height(tree);
|
||||
int balance = avl_balance(tree);
|
||||
if(balance > 1 && key < tree->left->key)
|
||||
{
|
||||
return avl_right_rotate(tree);
|
||||
}
|
||||
else if(balance < -1 && key > tree->right->key)
|
||||
{
|
||||
return avl_left_rotate(tree);
|
||||
}
|
||||
else if(balance > 1 && key > tree->left->key)
|
||||
{
|
||||
tree->left = avl_left_rotate(tree->left);
|
||||
return avl_right_rotate(tree);
|
||||
}
|
||||
else if(balance < -1 && key < tree->right->key)
|
||||
{
|
||||
tree->right = avl_right_rotate(tree->right);
|
||||
return avl_left_rotate(tree);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
struct avltree_t *avl_remove(struct avltree_t *tree, int key)
|
||||
{
|
||||
if(tree == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if(key < tree->key)
|
||||
{
|
||||
tree->left = avl_remove(tree->left, key);
|
||||
}
|
||||
else if(key > tree->key)
|
||||
{
|
||||
tree->right = avl_remove(tree->right, key);
|
||||
}
|
||||
else if(tree->left == NULL || tree->right == NULL)
|
||||
{
|
||||
struct avltree_t *child = tree->left == NULL ? tree->right : tree->left;
|
||||
if(child == NULL)
|
||||
{
|
||||
child = tree;
|
||||
tree = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
*tree = *child;
|
||||
}
|
||||
kfree(child);
|
||||
}
|
||||
else
|
||||
{
|
||||
struct avltree_t *min = tree->right;
|
||||
while(min->left != NULL)
|
||||
{
|
||||
min = min->left;
|
||||
}
|
||||
tree->key = min->key;
|
||||
tree->value = min->value;
|
||||
tree->right = avl_remove(tree->right, min->key);
|
||||
}
|
||||
|
||||
if(tree == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
avl_update_height(tree);
|
||||
int balance = avl_balance(tree);
|
||||
if(balance > 1 && avl_balance(tree->left) >= 0)
|
||||
{
|
||||
return avl_right_rotate(tree);
|
||||
}
|
||||
else if(balance > 1 && avl_balance(tree->left) < 0)
|
||||
{
|
||||
tree->left = avl_left_rotate(tree->left);
|
||||
return avl_right_rotate(tree);
|
||||
}
|
||||
else if(balance < -1 && avl_balance(tree->right) <= 0)
|
||||
{
|
||||
return avl_left_rotate(tree);
|
||||
}
|
||||
else if(balance < -1 && avl_balance(tree->right) > 0)
|
||||
{
|
||||
tree->right = avl_right_rotate(tree->right);
|
||||
return avl_left_rotate(tree);
|
||||
}
|
||||
|
||||
return tree;
|
||||
}
|
||||
|
||||
void *avl_get(struct avltree_t *tree, int key)
|
||||
{
|
||||
if(tree == NULL)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
else if(key < tree->key)
|
||||
{
|
||||
return avl_get(tree->left, key);
|
||||
}
|
||||
else if(key > tree->key)
|
||||
{
|
||||
return avl_get(tree->right, key);
|
||||
}
|
||||
else
|
||||
{
|
||||
return tree->value;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user