mirror of
https://github.com/bkthomps/Containers.git
synced 2025-12-05 15:15:49 +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,
|
static struct node *map_repair(map me,
|
||||||
struct node *const parent,
|
struct node *const parent,
|
||||||
struct node *const child,
|
struct node *const child,
|
||||||
struct node *const grand_child)
|
struct node *const grand_child)
|
||||||
{
|
{
|
||||||
if (parent->balance == 2 && child->balance >= 0) {
|
if (parent->balance == 2) {
|
||||||
map_rotate_left(me, parent, child);
|
if (child->balance == -1) {
|
||||||
if (child->balance == 0) {
|
return map_repair_right_left(me, parent, child, grand_child);
|
||||||
parent->balance = 1;
|
|
||||||
child->balance = -1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
}
|
||||||
return child;
|
return map_repair_left(me, parent, child);
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance <= 0) {
|
if (child->balance == 1) {
|
||||||
map_rotate_right(me, parent, child);
|
return map_repair_left_right(me, parent, child, grand_child);
|
||||||
if (child->balance == 0) {
|
|
||||||
parent->balance = -1;
|
|
||||||
child->balance = 1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance == 1) {
|
return map_repair_right(me, parent, 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;
|
|
||||||
}
|
|
||||||
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. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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,
|
static void map_trace_ancestors(map me, struct node *item)
|
||||||
struct node *item,
|
|
||||||
const int is_left_deleted)
|
|
||||||
{
|
{
|
||||||
struct node *child;
|
struct node *child = item;
|
||||||
struct node *parent;
|
struct node *parent = item->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;
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent->left == child) {
|
if (parent->left == child) {
|
||||||
parent->balance++;
|
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.
|
* 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,
|
static struct node *multimap_repair(multimap me,
|
||||||
struct node *const parent,
|
struct node *const parent,
|
||||||
struct node *const child,
|
struct node *const child,
|
||||||
struct node *const grand_child)
|
struct node *const grand_child)
|
||||||
{
|
{
|
||||||
if (parent->balance == 2 && child->balance >= 0) {
|
if (parent->balance == 2) {
|
||||||
multimap_rotate_left(me, parent, child);
|
if (child->balance == -1) {
|
||||||
if (child->balance == 0) {
|
return multimap_repair_right_left(me, parent, child, grand_child);
|
||||||
parent->balance = 1;
|
|
||||||
child->balance = -1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
}
|
||||||
return child;
|
return multimap_repair_left(me, parent, child);
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance <= 0) {
|
if (child->balance == 1) {
|
||||||
multimap_rotate_right(me, parent, child);
|
return multimap_repair_left_right(me, parent, child, grand_child);
|
||||||
if (child->balance == 0) {
|
|
||||||
parent->balance = -1;
|
|
||||||
child->balance = 1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance == 1) {
|
return multimap_repair_right(me, parent, 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;
|
|
||||||
}
|
|
||||||
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. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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,
|
static void multimap_trace_ancestors(multimap me, struct node *item)
|
||||||
struct node *item,
|
|
||||||
const int is_left_deleted)
|
|
||||||
{
|
{
|
||||||
struct node *child;
|
struct node *child = item;
|
||||||
struct node *parent;
|
struct node *parent = item->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;
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent->left == child) {
|
if (parent->left == child) {
|
||||||
parent->balance++;
|
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.
|
* 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,
|
static struct node *multiset_repair(multiset me,
|
||||||
struct node *const parent,
|
struct node *const parent,
|
||||||
struct node *const child,
|
struct node *const child,
|
||||||
struct node *const grand_child)
|
struct node *const grand_child)
|
||||||
{
|
{
|
||||||
if (parent->balance == 2 && child->balance >= 0) {
|
if (parent->balance == 2) {
|
||||||
multiset_rotate_left(me, parent, child);
|
if (child->balance == -1) {
|
||||||
if (child->balance == 0) {
|
return multiset_repair_right_left(me, parent, child, grand_child);
|
||||||
parent->balance = 1;
|
|
||||||
child->balance = -1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
}
|
||||||
return child;
|
return multiset_repair_left(me, parent, child);
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance <= 0) {
|
if (child->balance == 1) {
|
||||||
multiset_rotate_right(me, parent, child);
|
return multiset_repair_left_right(me, parent, child, grand_child);
|
||||||
if (child->balance == 0) {
|
|
||||||
parent->balance = -1;
|
|
||||||
child->balance = 1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance == 1) {
|
return multiset_repair_right(me, parent, 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;
|
|
||||||
}
|
|
||||||
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. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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,
|
static void multiset_trace_ancestors(multiset me, struct node *item)
|
||||||
struct node *item,
|
|
||||||
const int is_left_deleted)
|
|
||||||
{
|
{
|
||||||
struct node *child;
|
struct node *child = item;
|
||||||
struct node *parent;
|
struct node *parent = item->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;
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent->left == child) {
|
if (parent->left == child) {
|
||||||
parent->balance++;
|
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.
|
* 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,
|
static struct node *set_repair(set me,
|
||||||
struct node *const parent,
|
struct node *const parent,
|
||||||
struct node *const child,
|
struct node *const child,
|
||||||
struct node *const grand_child)
|
struct node *const grand_child)
|
||||||
{
|
{
|
||||||
if (parent->balance == 2 && child->balance >= 0) {
|
if (parent->balance == 2) {
|
||||||
set_rotate_left(me, parent, child);
|
if (child->balance == -1) {
|
||||||
if (child->balance == 0) {
|
return set_repair_right_left(me, parent, child, grand_child);
|
||||||
parent->balance = 1;
|
|
||||||
child->balance = -1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
}
|
||||||
return child;
|
return set_repair_left(me, parent, child);
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance <= 0) {
|
if (child->balance == 1) {
|
||||||
set_rotate_right(me, parent, child);
|
return set_repair_left_right(me, parent, child, grand_child);
|
||||||
if (child->balance == 0) {
|
|
||||||
parent->balance = -1;
|
|
||||||
child->balance = 1;
|
|
||||||
} else {
|
|
||||||
parent->balance = 0;
|
|
||||||
child->balance = 0;
|
|
||||||
}
|
|
||||||
return child;
|
|
||||||
}
|
}
|
||||||
if (parent->balance == -2 && child->balance == 1) {
|
return set_repair_right(me, parent, 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;
|
|
||||||
}
|
|
||||||
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. */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -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,
|
static void set_trace_ancestors(set me, struct node *item)
|
||||||
struct node *item,
|
|
||||||
const int is_left_deleted)
|
|
||||||
{
|
{
|
||||||
struct node *child;
|
struct node *child = item;
|
||||||
struct node *parent;
|
struct node *parent = item->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;
|
|
||||||
while (parent) {
|
while (parent) {
|
||||||
if (parent->left == child) {
|
if (parent->left == child) {
|
||||||
parent->balance++;
|
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.
|
* Removes traverse when it has no children.
|
||||||
*/
|
*/
|
||||||
|
|||||||
Reference in New Issue
Block a user