Weak AVL Tree Implementation 4
Fri, Aug 9 2024 18:42:12 KSTSimplification of the balance
function
I remove #define TOLERANCE 1
and simplify the balance
function.
The balance
function has the following code:
((rank(h->left) > rank(h->right)) &&
((rank(h->left) - rank(h->right)) > 1))
The above code can be simplified as follows:
l > r &&
l - r > 1
l - r > r - r &&
l - r > 1
l - r > 0 &&
l - r > 1
l - r > 1
So the rewritten balance
function is:
Node* balance (Node* h)
{
if ((rank(h->left) - rank(h->right) > 1))
{
if (rank(h->left->right) > rank(h->left->left))
h->left = right_rotate (h->left);
h = left_rotate (h);
}
else
{
if ((rank(h->right) - rank(h->left) > 1))
{
if (rank(h->right->left) > rank(h->right->right))
h->right = left_rotate (h->right);
h = right_rotate (h);
}
}
update_rank (h);
return h;
}
Verification
Even if the input data is the same, the shape of the tree can change if the input order changes. Therefore, we need a code to verify whether the tree is a Weak AVL tree.
This alone is not enough. We also need to check whether n outputs are generated when n different data are input.
To check this, we create an int size
variable.
typedef struct _Tree Tree;
struct _Tree {
Node* root;
int size;
};
Tree* tree_new ()
{
Tree* tree = malloc (sizeof (Tree));
tree->root = nullptr;
tree->size = 0;
return tree;
}
We modify insert
function to increase size
when inserting a node.
void tree_insert (Tree* tree, int key)
{
tree->root = insert (tree, tree->root, key);
}
Node* insert (Tree* tree, Node* h, int key)
{
if (h == nullptr)
{
tree->size++;
return node_new (key);
}
if (key < h->key)
h->left = insert (tree, h->left, key);
else if (key > h->key)
h->right = insert (tree, h->right, key);
else // On a hit, size is not increased and the balance function is not performed.
return h;
return balance (h);
}
I decided to modify the traverse
function to a verify
function.
void verify (Node* node, int* count)
{
if (!node)
return;
verify (node->left, count);
if (node->left)
printf ("%d(%d)\t", node->left->key, node->left->rank);
else
printf (" \t");
printf ("%d(%d)", node->key, node->rank);
if (node->right)
printf ("\t%d(%d)", node->right->key, node->right->rank);
else
printf ("\t");
puts ("");
// All leaf nodes have rank 0.
if (!node->left && !node->right)
assert (node->rank == 0);
if (node->left && node->right && // An internal node
!node->left->left && !node->left->right &&
!node->right->left && !node->right->right) // with two leaf nodes
assert (node->rank == 1); // has rank 1.
// The rank difference from the parent node is 1 or 2.
int diff;
diff = abs (rank(node) - rank(node->left));
assert (diff == 1 || diff == 2);
diff = abs (rank(node) - rank(node->right));
assert (diff == 1 || diff == 2);
(*count)++;
verify (node->right, count);
}
void tree_verify (Tree* tree, int size)
{
int count = 0;
verify (tree->root, &count);
assert (tree->size == size);
assert (tree->size == count);
}
int main ()
{
int numbers[] = {
29, 13, 23, 59, 25, 20, 5, 9, 33, 2, 31, 18, 11, 37, 7, 98,
// duplicate keys
31, 2, 13, 25, 9, 18, 37, 29, 23, 98, 20, 59, 5, 7, 11, 33
};
Tree* tree = tree_new ();
for (int i = 0; i < sizeof (numbers) / sizeof (numbers[0]); i++)
tree_insert (tree, numbers[i]);
tree_verify (tree, 16);
tree_free (tree);
return 0;
}