2016-05-24 07:27:26 +00:00
|
|
|
/* Copyright 2016 secXsQuared
|
|
|
|
* Distributed under GPL license
|
|
|
|
* See COPYING under root for details
|
|
|
|
*/
|
|
|
|
|
2016-08-27 05:13:54 +00:00
|
|
|
#include "k_avl_tree.h"
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static inline int32_t KAPI _avl_tree_node_get_height(k_avl_tree_node_t *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
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static inline int32_t KAPI _avl_tree_node_get_balance_factor(k_avl_tree_node_t *node)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-01 09:11:58 +00:00
|
|
|
if (node == NULL)
|
|
|
|
return 0;
|
2015-03-21 21:17:38 +00:00
|
|
|
return _avl_tree_node_get_height(node->left) - _avl_tree_node_get_height(node->right);
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_right_rotate(k_avl_tree_node_t *root)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *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
|
2016-08-27 05:13:54 +00:00
|
|
|
root->height = ke_max_32(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
|
2016-06-17 01:13:57 +00:00
|
|
|
left_children->height =
|
2016-08-27 05:13:54 +00:00
|
|
|
ke_max_32(_avl_tree_node_get_height(left_children->left), _avl_tree_node_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
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_left_rotate(k_avl_tree_node_t *root)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *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;
|
|
|
|
|
2016-08-27 05:13:54 +00:00
|
|
|
root->height = ke_max_32(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
|
2016-06-17 01:13:57 +00:00
|
|
|
right_children->height =
|
2016-08-27 05:13:54 +00:00
|
|
|
ke_max_32(_avl_tree_node_get_height(right_children->left), _avl_tree_node_get_height(right_children->right)) +
|
2016-06-17 01:13:57 +00:00
|
|
|
1;
|
2015-03-01 09:11:58 +00:00
|
|
|
return right_children;
|
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_balance(k_avl_tree_node_t *node)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t bf = _avl_tree_node_get_balance_factor(node);
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-01 09:11:58 +00:00
|
|
|
if (bf > 1)
|
|
|
|
{
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t left_bf = _avl_tree_node_get_balance_factor(node->left);
|
2015-03-01 09:11:58 +00:00
|
|
|
if (left_bf >= 0)
|
|
|
|
//left left
|
2015-03-21 21:17:38 +00:00
|
|
|
return _avl_tree_node_right_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
else
|
|
|
|
{
|
|
|
|
//left right
|
2015-03-21 21:17:38 +00:00
|
|
|
node->left = _avl_tree_node_left_rotate(node->left);
|
|
|
|
return _avl_tree_node_right_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else if (bf < -1)
|
|
|
|
{
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t right_bf = _avl_tree_node_get_balance_factor(node->right);
|
2015-03-01 09:11:58 +00:00
|
|
|
if (right_bf <= 0)
|
|
|
|
{
|
|
|
|
// right right
|
2015-03-21 21:17:38 +00:00
|
|
|
return _avl_tree_node_left_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
// right left
|
2015-03-21 21:17:38 +00:00
|
|
|
node->right = _avl_tree_node_right_rotate(node->right);
|
|
|
|
return _avl_tree_node_left_rotate(node);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
return node;
|
2015-02-21 10:47:24 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_insert(k_avl_tree_node_t *root, k_avl_tree_node_t *node,
|
|
|
|
k_callback_func_t compare,
|
|
|
|
k_avl_tree_node_t *parent)
|
2015-03-16 02:02:45 +00:00
|
|
|
{
|
2016-05-22 01:54:29 +00:00
|
|
|
if (node == NULL || compare == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return root;
|
|
|
|
if (root == NULL)
|
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
node->parent = parent;
|
|
|
|
return node;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t comp = compare(root, node);
|
2015-03-01 09:11:58 +00:00
|
|
|
if (comp < 0)
|
2015-03-21 21:17:38 +00:00
|
|
|
root->right = _avl_tree_node_insert(root->right, node, 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-21 21:17:38 +00:00
|
|
|
root->left = _avl_tree_node_insert(root->left, node, compare, root);
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2016-08-27 05:13:54 +00:00
|
|
|
root->height = ke_max_32(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2015-03-21 21:17:38 +00:00
|
|
|
return _avl_tree_node_balance(root);
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static void _avl_tree_swap_nodes(k_avl_tree_node_t *node1, k_avl_tree_node_t *node2)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
if (node1 == NULL || node2 == NULL)
|
|
|
|
return;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *parent = NULL;
|
|
|
|
k_avl_tree_node_t *child = NULL;
|
|
|
|
k_avl_tree_node_t *temp = NULL;
|
2015-03-21 21:17:38 +00:00
|
|
|
//swap node but does not change anything else other than node1,node2
|
|
|
|
if (node1->parent != NULL && node1->parent == node2)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
parent = node2;
|
|
|
|
child = node1;
|
|
|
|
}
|
|
|
|
else if (node2->parent != NULL && node2->parent == node1)
|
|
|
|
{
|
|
|
|
parent = node1;
|
|
|
|
child = node2;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (parent != NULL && child != NULL)
|
|
|
|
{
|
|
|
|
//connected case
|
2016-06-17 01:13:57 +00:00
|
|
|
if (parent->parent != NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (parent->parent->left == parent)
|
2015-03-21 21:17:38 +00:00
|
|
|
parent->parent->left = child;
|
|
|
|
else
|
|
|
|
parent->parent->right = child;
|
|
|
|
}
|
|
|
|
//update left/right for parent
|
2016-06-17 01:13:57 +00:00
|
|
|
if (parent->left != NULL && child != parent->left)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
|
|
|
parent->left->parent = child;
|
|
|
|
}
|
2016-06-17 01:13:57 +00:00
|
|
|
if (parent->right != NULL && child != parent->right)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
|
|
|
parent->right->parent = child;
|
|
|
|
}
|
|
|
|
//update left/right for children
|
2016-06-17 01:13:57 +00:00
|
|
|
if (child->left != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
child->left->parent = parent;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (child->right != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
child->right->parent = parent;
|
|
|
|
|
|
|
|
child->parent = parent->parent;
|
|
|
|
parent->parent = child;
|
|
|
|
if (child == parent->left)
|
|
|
|
{
|
2016-05-17 19:03:18 +00:00
|
|
|
/* parent
|
|
|
|
/ \
|
|
|
|
children */
|
2015-03-21 21:17:38 +00:00
|
|
|
parent->left = child->left;
|
|
|
|
child->left = parent;
|
|
|
|
|
|
|
|
temp = parent->right;
|
|
|
|
parent->right = child->right;
|
|
|
|
child->right = temp;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-03-21 21:17:38 +00:00
|
|
|
else
|
|
|
|
{
|
2016-05-17 19:03:18 +00:00
|
|
|
/* parent
|
|
|
|
/ \
|
|
|
|
children */
|
2015-03-21 21:17:38 +00:00
|
|
|
parent->right = child->right;
|
|
|
|
child->right = parent;
|
|
|
|
|
|
|
|
temp = parent->left;
|
|
|
|
parent->left = child->left;
|
|
|
|
child->left = temp;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
//not connected case
|
|
|
|
//adjust all the nodes other than node1,node2
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node1->left != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
node1->left->parent = node2;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node1->right != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
node1->right->parent = node2;
|
|
|
|
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node2->left != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
node2->left->parent = node1;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node2->right != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
node2->right->parent = node1;
|
|
|
|
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node1->parent != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node1->parent->left == node1)
|
2015-03-21 21:17:38 +00:00
|
|
|
node1->parent->left = node2;
|
|
|
|
else
|
|
|
|
node1->parent->right = node2;
|
|
|
|
}
|
|
|
|
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node2->parent != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (node2->parent->left == node2)
|
2015-03-21 21:17:38 +00:00
|
|
|
node2->parent->left = node1;
|
|
|
|
else
|
|
|
|
node2->parent->right = node1;
|
|
|
|
}
|
|
|
|
|
|
|
|
//adjust node1,node2
|
|
|
|
temp = node1->parent;
|
|
|
|
node1->parent = node2->parent;
|
|
|
|
node2->parent = temp;
|
|
|
|
|
|
|
|
temp = node1->left;
|
|
|
|
node1->left = node2->left;
|
|
|
|
node2->left = temp;
|
|
|
|
|
|
|
|
temp = node1->right;
|
|
|
|
node1->right = node2->right;
|
|
|
|
node2->right = temp;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-03-21 21:17:38 +00:00
|
|
|
|
|
|
|
//swap height
|
2016-05-22 01:54:29 +00:00
|
|
|
int32_t height = node1->height;
|
2015-03-21 21:17:38 +00:00
|
|
|
node1->height = node2->height;
|
|
|
|
node2->height = height;
|
2015-03-16 02:02:45 +00:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_delete(k_avl_tree_node_t *root,
|
|
|
|
k_avl_tree_node_t *node,
|
|
|
|
k_callback_func_t compare,
|
|
|
|
k_avl_tree_node_t **deleted_node)
|
2015-03-16 02:02:45 +00:00
|
|
|
{
|
2016-06-25 07:25:54 +00:00
|
|
|
if (root == NULL || node == NULL || compare == NULL || deleted_node == NULL)
|
2015-03-16 02:02:45 +00:00
|
|
|
return root;
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t comp = compare(root, node);
|
2015-03-16 02:02:45 +00:00
|
|
|
if (comp < 0)
|
2016-06-25 07:25:54 +00:00
|
|
|
root->right = _avl_tree_node_delete(root->right, node, compare, deleted_node);
|
2016-06-17 01:13:57 +00:00
|
|
|
else if (comp > 0)
|
2016-06-25 07:25:54 +00:00
|
|
|
root->left = _avl_tree_node_delete(root->left, node, compare, deleted_node);
|
2015-03-01 09:11:58 +00:00
|
|
|
else
|
|
|
|
{
|
2016-06-25 07:25:54 +00:00
|
|
|
*deleted_node = root;
|
2015-03-16 02:02:45 +00:00
|
|
|
// node with only one child or no child
|
2016-06-17 01:13:57 +00:00
|
|
|
if ((root->left == NULL) || (root->right == NULL))
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *child = root->left != NULL ? root->left : root->right;
|
2015-03-16 02:02:45 +00:00
|
|
|
|
2016-06-17 01:13:57 +00:00
|
|
|
if (child == NULL)
|
2015-03-16 02:02:45 +00:00
|
|
|
{ // 0 child
|
|
|
|
root = NULL;
|
|
|
|
}
|
|
|
|
else // 1 child
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
child->parent = root->parent;
|
|
|
|
root = 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)
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *successor = ke_avl_tree_larger(root);
|
2015-03-21 21:17:38 +00:00
|
|
|
//swap fields
|
2015-09-04 19:04:22 +00:00
|
|
|
_avl_tree_swap_nodes(successor, root);
|
2015-03-16 02:02:45 +00:00
|
|
|
|
2015-03-21 21:17:38 +00:00
|
|
|
// Detach the inorder successor
|
2016-06-25 07:25:54 +00:00
|
|
|
successor->right = _avl_tree_node_delete(successor->right, root, compare, deleted_node);
|
2015-03-16 02:02:45 +00:00
|
|
|
|
2015-03-21 21:17:38 +00:00
|
|
|
root = successor;
|
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;
|
2016-08-27 05:13:54 +00:00
|
|
|
root->height = ke_max_32(_avl_tree_node_get_height(root->left), _avl_tree_node_get_height(root->right)) + 1;
|
2015-03-21 21:17:38 +00:00
|
|
|
root = _avl_tree_node_balance(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
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static k_avl_tree_node_t *KAPI _avl_tree_node_search(k_avl_tree_node_t *root, k_avl_tree_node_t *node,
|
|
|
|
k_callback_func_t compare)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (root == NULL || compare == NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
return NULL;
|
2016-05-22 01:54:29 +00:00
|
|
|
const int32_t comp = compare(root, node);
|
2015-03-21 21:17:38 +00:00
|
|
|
if (comp < 0)
|
2016-05-17 19:03:18 +00:00
|
|
|
return _avl_tree_node_search(root->right, node, compare);
|
2015-03-21 21:17:38 +00:00
|
|
|
else if (comp == 0)
|
|
|
|
return root;
|
|
|
|
else
|
2016-05-17 19:03:18 +00:00
|
|
|
return _avl_tree_node_search(root->left, node, compare);
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
|
|
|
|
2016-06-17 01:13:57 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static void KAPI _avl_tree_node_init(k_avl_tree_node_t *it)
|
2015-02-21 10:47:24 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (it != NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
it->height = 0;
|
|
|
|
it->left = NULL;
|
|
|
|
it->right = NULL;
|
|
|
|
it->parent = NULL;
|
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-16 02:02:45 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_smallest(k_avl_tree_t *tree)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-05-20 19:07:11 +00:00
|
|
|
if (tree == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return NULL;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *entry = tree->root;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (entry == NULL)
|
2016-05-20 19:07:11 +00:00
|
|
|
return NULL;
|
|
|
|
while (entry->left != NULL)
|
|
|
|
entry = entry->left;
|
|
|
|
return entry;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
2015-02-21 10:47:24 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_largest(k_avl_tree_t *tree)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2016-05-20 19:07:11 +00:00
|
|
|
if (tree == NULL)
|
2015-03-01 09:11:58 +00:00
|
|
|
return NULL;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *entry = tree->root;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (entry == NULL)
|
2016-05-20 19:07:11 +00:00
|
|
|
return NULL;
|
|
|
|
while (entry->right != NULL)
|
|
|
|
entry = entry->right;
|
|
|
|
return entry;
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2015-03-21 21:17:38 +00:00
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_larger(k_avl_tree_node_t *it)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
if (it == NULL)
|
|
|
|
return NULL;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *root = it;
|
2015-03-16 02:02:45 +00:00
|
|
|
if (root->right != NULL)
|
|
|
|
{
|
|
|
|
root = root->right;
|
|
|
|
while (root->left != NULL)
|
|
|
|
root = root->left;
|
2015-03-21 21:17:38 +00:00
|
|
|
return root;
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
while (root->parent != NULL)
|
|
|
|
{
|
|
|
|
if (root->parent->left == root)
|
2015-03-21 21:17:38 +00:00
|
|
|
return root->parent;
|
2015-03-16 02:02:45 +00:00
|
|
|
root = root->parent;
|
|
|
|
}
|
2015-03-21 21:17:38 +00:00
|
|
|
return NULL;
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
2015-03-01 09:11:58 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_smaller(k_avl_tree_node_t *it)
|
2015-03-01 09:11:58 +00:00
|
|
|
{
|
2015-03-21 21:17:38 +00:00
|
|
|
if (it == NULL)
|
|
|
|
return NULL;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *root = it;
|
2015-03-16 02:02:45 +00:00
|
|
|
if (root->left != NULL)
|
|
|
|
{
|
|
|
|
root = root->left;
|
|
|
|
while (root->right != NULL)
|
|
|
|
root = root->right;
|
2015-03-21 21:17:38 +00:00
|
|
|
return root;
|
2015-03-16 02:02:45 +00:00
|
|
|
}
|
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-03-21 21:17:38 +00:00
|
|
|
return root->parent;
|
2015-03-16 02:02:45 +00:00
|
|
|
root = root->parent;
|
2015-02-21 10:47:24 +00:00
|
|
|
}
|
2015-03-21 21:17:38 +00:00
|
|
|
return 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
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_search(k_avl_tree_t *tree, k_avl_tree_node_t *node)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
return _avl_tree_node_search(tree->root, node, tree->compare);
|
2015-03-21 21:17:38 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
void KAPI ke_avl_tree_insert(k_avl_tree_t *tree, k_avl_tree_node_t *data)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree != NULL && data != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-05-22 08:24:08 +00:00
|
|
|
_avl_tree_node_init(data);
|
2016-06-17 01:13:57 +00:00
|
|
|
tree->root = _avl_tree_node_insert(tree->root, data, tree->compare, NULL);
|
2015-03-21 21:17:38 +00:00
|
|
|
}
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *KAPI ke_avl_tree_delete(k_avl_tree_t *tree, k_avl_tree_node_t *data)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *node = NULL;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree != NULL && data != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-25 07:25:54 +00:00
|
|
|
tree->root = _avl_tree_node_delete(tree->root, data, tree->compare, &node);
|
2015-03-21 21:17:38 +00:00
|
|
|
}
|
2016-06-25 07:25:54 +00:00
|
|
|
return node;
|
2015-03-21 21:17:38 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
int32_t KAPI ke_avl_tree_size(k_avl_tree_t *tree)
|
2016-05-20 19:07:11 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree == NULL)
|
2016-05-20 19:07:11 +00:00
|
|
|
return -1;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree->root == NULL)
|
2016-05-20 19:07:11 +00:00
|
|
|
return 0;
|
2016-06-17 01:13:57 +00:00
|
|
|
int32_t size = 0;
|
2016-08-28 00:20:38 +00:00
|
|
|
k_avl_tree_node_t *entry = ke_avl_tree_smallest(tree);
|
2016-06-17 01:13:57 +00:00
|
|
|
while (entry != NULL)
|
2016-05-20 19:07:11 +00:00
|
|
|
{
|
|
|
|
size++;
|
2016-08-28 00:20:38 +00:00
|
|
|
entry = ke_avl_tree_larger(entry);
|
2016-05-20 19:07:11 +00:00
|
|
|
}
|
|
|
|
return size;
|
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
void KAPI ke_avl_tree_init(k_avl_tree_t *tree, k_callback_func_t compare)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree != NULL)
|
2015-03-21 21:17:38 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
tree->compare = compare;
|
2015-03-21 21:17:38 +00:00
|
|
|
tree->root = NULL;
|
|
|
|
}
|
|
|
|
return;
|
2016-05-22 08:24:08 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// TESTING STUFF
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static int32_t KAPI _avl_tree_node_calculate_height(k_avl_tree_node_t *tree)
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
|
|
|
if (tree == NULL)
|
|
|
|
return -1;
|
2016-08-27 05:13:54 +00:00
|
|
|
return ke_max_32(_avl_tree_node_calculate_height(tree->left), _avl_tree_node_calculate_height(tree->right)) + 1;
|
2016-05-22 08:24:08 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
static bool KAPI _avl_tree_node_test(k_avl_tree_node_t *tree, int32_t (*compare)(k_avl_tree_node_t *, k_avl_tree_node_t *))
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
|
|
|
if (tree == NULL)
|
|
|
|
return true;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (_avl_tree_node_get_balance_factor(tree) < -1 || _avl_tree_node_get_balance_factor(tree) > 1 ||
|
|
|
|
_avl_tree_node_calculate_height(tree) != tree->height)
|
2016-05-22 08:24:08 +00:00
|
|
|
return false;
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree->left != NULL)
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree->left->parent != tree)
|
2016-05-22 08:24:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree->right != NULL)
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree->right->parent != tree)
|
2016-05-22 08:24:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-06-17 01:13:57 +00:00
|
|
|
if (compare != NULL)
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if ((tree->right != NULL && compare(tree, tree->right) > 0) ||
|
|
|
|
(tree->left != NULL && compare(tree, tree->left) < 0))
|
2016-05-22 08:24:08 +00:00
|
|
|
return false;
|
|
|
|
}
|
2016-06-17 01:13:57 +00:00
|
|
|
return _avl_tree_node_test(tree->left, compare) && _avl_tree_node_test(tree->right, compare);
|
2016-05-22 08:24:08 +00:00
|
|
|
}
|
|
|
|
|
2016-08-28 00:20:38 +00:00
|
|
|
bool KAPI ke_avl_tree_validate(k_avl_tree_t *tree)
|
2016-05-22 08:24:08 +00:00
|
|
|
{
|
2016-06-17 01:13:57 +00:00
|
|
|
if (tree == NULL)
|
2016-05-22 08:24:08 +00:00
|
|
|
return true;
|
2016-06-17 01:13:57 +00:00
|
|
|
return _avl_tree_node_test(tree->root, tree->compare);
|
2016-05-22 01:54:29 +00:00
|
|
|
}
|