mirror of
https://github.com/bkthomps/Containers.git
synced 2025-11-16 04:24:47 +00:00
Refactor source code (#32)
Refactor large functions into smaller functions.
This commit is contained in:
200
src/map.c
200
src/map.c
@@ -150,68 +150,108 @@ static void map_rotate_right(map me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert.
|
||||
* Performs a left repair.
|
||||
*/
|
||||
static struct node *map_repair_left(map me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
map_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right repair.
|
||||
*/
|
||||
static struct node *map_repair_right(map me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
map_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a left-right repair.
|
||||
*/
|
||||
static struct node *map_repair_left_right(map me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
map_rotate_left(me, child, grand_child);
|
||||
map_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right-left repair.
|
||||
*/
|
||||
static struct node *map_repair_right_left(map me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
map_rotate_right(me, child, grand_child);
|
||||
map_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert. The only possible values of parent->balance
|
||||
* are {-2, 2} and the only possible values of child->balance are {-1, 0, 1}.
|
||||
*/
|
||||
static struct node *map_repair(map me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
if (parent->balance == 2 && child->balance >= 0) {
|
||||
map_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
if (parent->balance == 2) {
|
||||
if (child->balance == -1) {
|
||||
return map_repair_right_left(me, parent, child, grand_child);
|
||||
}
|
||||
return child;
|
||||
return map_repair_left(me, parent, child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance <= 0) {
|
||||
map_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
if (child->balance == 1) {
|
||||
return map_repair_left_right(me, parent, child, grand_child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance == 1) {
|
||||
map_rotate_left(me, child, grand_child);
|
||||
map_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
if (parent->balance == 2 && child->balance == -1) {
|
||||
map_rotate_right(me, child, grand_child);
|
||||
map_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
/* Impossible to get here. */
|
||||
return map_repair_right(me, parent, child);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -408,32 +448,12 @@ static struct node *map_repair_pivot(map me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
* Goes back up the tree repairing it along the way.
|
||||
*/
|
||||
static void map_delete_balance(map me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
static void map_trace_ancestors(map me, struct node *item)
|
||||
{
|
||||
struct node *child;
|
||||
struct node *parent;
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = map_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
child = item;
|
||||
parent = item->parent;
|
||||
struct node *child = item;
|
||||
struct node *parent = item->parent;
|
||||
while (parent) {
|
||||
if (parent->left == child) {
|
||||
parent->balance++;
|
||||
@@ -460,6 +480,32 @@ static void map_delete_balance(map me,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
*/
|
||||
static void map_delete_balance(map me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
{
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = map_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
map_trace_ancestors(me, item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes traverse when it has no children.
|
||||
*/
|
||||
|
||||
200
src/multimap.c
200
src/multimap.c
@@ -166,68 +166,108 @@ static void multimap_rotate_right(multimap me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert.
|
||||
* Performs a left repair.
|
||||
*/
|
||||
static struct node *multimap_repair_left(multimap me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
multimap_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right repair.
|
||||
*/
|
||||
static struct node *multimap_repair_right(multimap me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
multimap_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a left-right repair.
|
||||
*/
|
||||
static struct node *multimap_repair_left_right(multimap me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
multimap_rotate_left(me, child, grand_child);
|
||||
multimap_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right-left repair.
|
||||
*/
|
||||
static struct node *multimap_repair_right_left(multimap me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
multimap_rotate_right(me, child, grand_child);
|
||||
multimap_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert. The only possible values of parent->balance
|
||||
* are {-2, 2} and the only possible values of child->balance are {-1, 0, 1}.
|
||||
*/
|
||||
static struct node *multimap_repair(multimap me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
if (parent->balance == 2 && child->balance >= 0) {
|
||||
multimap_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
if (parent->balance == 2) {
|
||||
if (child->balance == -1) {
|
||||
return multimap_repair_right_left(me, parent, child, grand_child);
|
||||
}
|
||||
return child;
|
||||
return multimap_repair_left(me, parent, child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance <= 0) {
|
||||
multimap_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
if (child->balance == 1) {
|
||||
return multimap_repair_left_right(me, parent, child, grand_child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance == 1) {
|
||||
multimap_rotate_left(me, child, grand_child);
|
||||
multimap_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
if (parent->balance == 2 && child->balance == -1) {
|
||||
multimap_rotate_right(me, child, grand_child);
|
||||
multimap_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
/* Impossible to get here. */
|
||||
return multimap_repair_right(me, parent, child);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -487,32 +527,12 @@ static struct node *multimap_repair_pivot(multimap me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
* Goes back up the tree repairing it along the way.
|
||||
*/
|
||||
static void multimap_delete_balance(multimap me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
static void multimap_trace_ancestors(multimap me, struct node *item)
|
||||
{
|
||||
struct node *child;
|
||||
struct node *parent;
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = multimap_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
child = item;
|
||||
parent = item->parent;
|
||||
struct node *child = item;
|
||||
struct node *parent = item->parent;
|
||||
while (parent) {
|
||||
if (parent->left == child) {
|
||||
parent->balance++;
|
||||
@@ -539,6 +559,32 @@ static void multimap_delete_balance(multimap me,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
*/
|
||||
static void multimap_delete_balance(multimap me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
{
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = multimap_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
multimap_trace_ancestors(me, item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes traverse when it has no children.
|
||||
*/
|
||||
|
||||
200
src/multiset.c
200
src/multiset.c
@@ -148,68 +148,108 @@ static void multiset_rotate_right(multiset me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert.
|
||||
* Performs a left repair.
|
||||
*/
|
||||
static struct node *multiset_repair_left(multiset me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
multiset_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right repair.
|
||||
*/
|
||||
static struct node *multiset_repair_right(multiset me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
multiset_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a left-right repair.
|
||||
*/
|
||||
static struct node *multiset_repair_left_right(multiset me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
multiset_rotate_left(me, child, grand_child);
|
||||
multiset_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right-left repair.
|
||||
*/
|
||||
static struct node *multiset_repair_right_left(multiset me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
multiset_rotate_right(me, child, grand_child);
|
||||
multiset_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert. The only possible values of parent->balance
|
||||
* are {-2, 2} and the only possible values of child->balance are {-1, 0, 1}.
|
||||
*/
|
||||
static struct node *multiset_repair(multiset me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
if (parent->balance == 2 && child->balance >= 0) {
|
||||
multiset_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
if (parent->balance == 2) {
|
||||
if (child->balance == -1) {
|
||||
return multiset_repair_right_left(me, parent, child, grand_child);
|
||||
}
|
||||
return child;
|
||||
return multiset_repair_left(me, parent, child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance <= 0) {
|
||||
multiset_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
if (child->balance == 1) {
|
||||
return multiset_repair_left_right(me, parent, child, grand_child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance == 1) {
|
||||
multiset_rotate_left(me, child, grand_child);
|
||||
multiset_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
if (parent->balance == 2 && child->balance == -1) {
|
||||
multiset_rotate_right(me, child, grand_child);
|
||||
multiset_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
/* Impossible to get here. */
|
||||
return multiset_repair_right(me, parent, child);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -396,32 +436,12 @@ static struct node *multiset_repair_pivot(multiset me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
* Goes back up the tree repairing it along the way.
|
||||
*/
|
||||
static void multiset_delete_balance(multiset me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
static void multiset_trace_ancestors(multiset me, struct node *item)
|
||||
{
|
||||
struct node *child;
|
||||
struct node *parent;
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = multiset_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
child = item;
|
||||
parent = item->parent;
|
||||
struct node *child = item;
|
||||
struct node *parent = item->parent;
|
||||
while (parent) {
|
||||
if (parent->left == child) {
|
||||
parent->balance++;
|
||||
@@ -448,6 +468,32 @@ static void multiset_delete_balance(multiset me,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
*/
|
||||
static void multiset_delete_balance(multiset me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
{
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = multiset_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
multiset_trace_ancestors(me, item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes traverse when it has no children.
|
||||
*/
|
||||
|
||||
200
src/set.c
200
src/set.c
@@ -145,68 +145,108 @@ static void set_rotate_right(set me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert.
|
||||
* Performs a left repair.
|
||||
*/
|
||||
static struct node *set_repair_left(set me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
set_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right repair.
|
||||
*/
|
||||
static struct node *set_repair_right(set me,
|
||||
struct node *const parent,
|
||||
struct node *const child)
|
||||
{
|
||||
set_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a left-right repair.
|
||||
*/
|
||||
static struct node *set_repair_left_right(set me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
set_rotate_left(me, child, grand_child);
|
||||
set_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Performs a right-left repair.
|
||||
*/
|
||||
static struct node *set_repair_right_left(set me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
set_rotate_right(me, child, grand_child);
|
||||
set_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
|
||||
/*
|
||||
* Repairs the AVL tree on insert. The only possible values of parent->balance
|
||||
* are {-2, 2} and the only possible values of child->balance are {-1, 0, 1}.
|
||||
*/
|
||||
static struct node *set_repair(set me,
|
||||
struct node *const parent,
|
||||
struct node *const child,
|
||||
struct node *const grand_child)
|
||||
{
|
||||
if (parent->balance == 2 && child->balance >= 0) {
|
||||
set_rotate_left(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = 1;
|
||||
child->balance = -1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
if (parent->balance == 2) {
|
||||
if (child->balance == -1) {
|
||||
return set_repair_right_left(me, parent, child, grand_child);
|
||||
}
|
||||
return child;
|
||||
return set_repair_left(me, parent, child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance <= 0) {
|
||||
set_rotate_right(me, parent, child);
|
||||
if (child->balance == 0) {
|
||||
parent->balance = -1;
|
||||
child->balance = 1;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
}
|
||||
return child;
|
||||
if (child->balance == 1) {
|
||||
return set_repair_left_right(me, parent, child, grand_child);
|
||||
}
|
||||
if (parent->balance == -2 && child->balance == 1) {
|
||||
set_rotate_left(me, child, grand_child);
|
||||
set_rotate_right(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = 0;
|
||||
child->balance = -1;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 1;
|
||||
child->balance = 0;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
if (parent->balance == 2 && child->balance == -1) {
|
||||
set_rotate_right(me, child, grand_child);
|
||||
set_rotate_left(me, parent, grand_child);
|
||||
if (grand_child->balance == 1) {
|
||||
parent->balance = -1;
|
||||
child->balance = 0;
|
||||
} else if (grand_child->balance == 0) {
|
||||
parent->balance = 0;
|
||||
child->balance = 0;
|
||||
} else {
|
||||
parent->balance = 0;
|
||||
child->balance = 1;
|
||||
}
|
||||
grand_child->balance = 0;
|
||||
return grand_child;
|
||||
}
|
||||
/* Impossible to get here. */
|
||||
return set_repair_right(me, parent, child);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -373,32 +413,12 @@ static struct node *set_repair_pivot(set me,
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
* Goes back up the tree repairing it along the way.
|
||||
*/
|
||||
static void set_delete_balance(set me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
static void set_trace_ancestors(set me, struct node *item)
|
||||
{
|
||||
struct node *child;
|
||||
struct node *parent;
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = set_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
child = item;
|
||||
parent = item->parent;
|
||||
struct node *child = item;
|
||||
struct node *parent = item->parent;
|
||||
while (parent) {
|
||||
if (parent->left == child) {
|
||||
parent->balance++;
|
||||
@@ -425,6 +445,32 @@ static void set_delete_balance(set me,
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Balances the AVL tree on deletion.
|
||||
*/
|
||||
static void set_delete_balance(set me,
|
||||
struct node *item,
|
||||
const int is_left_deleted)
|
||||
{
|
||||
if (is_left_deleted) {
|
||||
item->balance++;
|
||||
} else {
|
||||
item->balance--;
|
||||
}
|
||||
/* If balance is -1 or +1 after modification, then the tree is balanced. */
|
||||
if (item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
/* Must re-balance if not in {-1, 0, 1} */
|
||||
if (item->balance > 1 || item->balance < -1) {
|
||||
item = set_repair_pivot(me, item, is_left_deleted);
|
||||
if (!item->parent || item->balance == -1 || item->balance == 1) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
set_trace_ancestors(me, item);
|
||||
}
|
||||
|
||||
/*
|
||||
* Removes traverse when it has no children.
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user