[Xfce4-commits] <squeeze:master> Balance the btree
Peter de Ridder
noreply at xfce.org
Thu Dec 22 23:00:02 CET 2011
Updating branch refs/heads/master
to f3472d91253a3016d68e2941b128a0d96f52ae00 (commit)
from d3cc31e6fb872e00eaad4291746c551435eea1c2 (commit)
commit f3472d91253a3016d68e2941b128a0d96f52ae00
Author: Peter de Ridder <peter at xfce.org>
Date: Tue Oct 4 21:42:13 2011 +0200
Balance the btree
btree delete isn't supported
libsqueeze/archive-iter.c | 2 +-
libsqueeze/archive.c | 4 -
libsqueeze/btree.c | 153 ++++++++++++++++++++++++++++++++++++++++++++-
libsqueeze/btree.h | 1 +
4 files changed, 153 insertions(+), 7 deletions(-)
diff --git a/libsqueeze/archive-iter.c b/libsqueeze/archive-iter.c
index 8762777..e713cb3 100644
--- a/libsqueeze/archive-iter.c
+++ b/libsqueeze/archive-iter.c
@@ -29,7 +29,7 @@
#include "internals.h"
#ifndef LSQ_ENTRY_CHILD_BUFFER_SIZE
-#define LSQ_ENTRY_CHILD_BUFFER_SIZE 500
+#define LSQ_ENTRY_CHILD_BUFFER_SIZE 8000
#endif
#ifdef LSQ_ENTRY_CHILD_BUFFER_DYNAMIC_SIZE
diff --git a/libsqueeze/archive.c b/libsqueeze/archive.c
index 262391b..fdac9f4 100644
--- a/libsqueeze/archive.c
+++ b/libsqueeze/archive.c
@@ -37,10 +37,6 @@
#include "internals.h"
-#ifndef LSQ_ENTRY_CHILD_BUFFER_SIZE
-#define LSQ_ENTRY_CHILD_BUFFER_SIZE 500
-#endif
-
static void
lsq_archive_class_init(LSQArchiveClass *archive_class);
diff --git a/libsqueeze/btree.c b/libsqueeze/btree.c
index 869bd80..ca3c49f 100644
--- a/libsqueeze/btree.c
+++ b/libsqueeze/btree.c
@@ -27,7 +27,7 @@
#include "btree.h"
#ifndef LSQ_BTREE_MAX_DEPTH
-#define LSQ_BTREE_MAX_DEPTH 500
+#define LSQ_BTREE_MAX_DEPTH 20
#endif
LSQBTree *
@@ -42,13 +42,19 @@ lsq_btree_insert_sorted_single (
LSQBTree *new_entry = NULL;
LSQBTree *stack[LSQ_BTREE_MAX_DEPTH];
guint stack_i = 0;
+ LSQArchiveEntry *swap_entry;
+ LSQBTree *swap_iter;
+ gint swap_balance;
+ gboolean short_side;
+ /* Check for a flat list */
if ( NULL != list && NULL != list->next )
{
g_critical("Cannot insert into a flattened tree");
return NULL;
}
+ /* Walk the btree */
for ( iter = list; NULL != iter; iter = *next )
{
/* archive can be NULL */
@@ -56,32 +62,175 @@ lsq_btree_insert_sorted_single (
if ( 0 > cmp )
{
+ /* Go the the left */
next = &iter->left;
}
else if ( 0 < cmp )
{
+ /* Go to the right */
next = &iter->right;
}
else
{
+ /* Logic outside this routine dictates we should never find a match */
g_critical("THIS SHOULD NOT HAPPEN!!! (the universe has just collapsed)");
return NULL;
}
+ /* Keep a stack of the path we followed */
+ g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
stack[stack_i++] = iter;
- g_return_val_if_fail(stack_i < LSQ_BTREE_MAX_DEPTH, NULL);
}
+ /* Create a new tree element */
new_entry = g_new0(LSQBTree, 1);
new_entry->entry = entry;
+ /* Check it this is a new tree */
if ( NULL == next )
{
return new_entry;
}
+ /* Store ourself in the parent */
*next = new_entry;
+ /* Balance the tree */
+ while ( 0 < stack_i )
+ {
+ iter = stack[--stack_i];
+
+ /* Calculate new the balance for the parent */
+ if ( iter->left == new_entry )
+ {
+ short_side = iter->balance > 0;
+ --iter->balance;
+ }
+ else
+ {
+ short_side = iter->balance < 0;
+ ++iter->balance;
+ }
+
+ /* The balance in the higher parents doesn't change when the short side changed */
+ if ( FALSE != short_side )
+ {
+ break;
+ }
+
+ if ( 1 < iter->balance )
+ {
+ /* Rotate left */
+ /* The code could be easier if we would just overwrite our parent left or right value.
+ * But instead we move that data from our right to our self and use the right tree link to be placed in the tree as if it was ourself.
+ */
+ /* Letters are tree nodes, numbers are the data. This illustrates a rotate right.
+ *
+ * A:4 | A:2
+ * / \ | / \
+ * B:2 C:5 | D:1 B:4
+ * / \ | / \
+ * D:1 E:3 | E:3 C:5
+ */
+ /* Swap the data */
+ swap_iter = iter->right;
+ swap_entry = iter->entry;
+ iter->entry = swap_iter->entry;
+ swap_iter->entry = swap_entry;
+
+ /* Reformat the tree links */
+ iter->right = swap_iter->right;
+ swap_iter->right = swap_iter->left;
+ swap_iter->left = iter->left;
+ iter->left = swap_iter;
+
+ /* Fix the balance values
+ *
+ * if B > 0
+ * A = A - 1 - B
+ * else
+ * A = A - 1
+ *
+ * diff = A - 1 - B
+ * if diff < 0
+ * B = B - 1 + diff
+ * else
+ * B = B - 1
+ */
+ swap_balance = swap_iter->balance;
+ swap_iter->balance = iter->balance - 1;
+ if ( 0 < swap_balance )
+ {
+ swap_iter->balance -= swap_balance;
+ }
+ iter->balance = iter->balance - 1 - swap_balance;
+ if ( 0 < iter->balance )
+ {
+ iter->balance = 0;
+ }
+ iter->balance += swap_balance - 1;
+
+ /* We added a child so our depth was increased, but we also saved depth by rotation so our parents depth stays the same */
+ if ( 0 < swap_balance )
+ {
+ break;
+ }
+ }
+ else if ( -1 > iter->balance )
+ {
+ /* Rotate right */
+ /* The code could be easier if we would just overwrite our parent left or right value.
+ * But instead we move that data from our left to our self and use the left tree link to be placed in the tree as if it was ourself.
+ */
+ /* Swap the data */
+ swap_iter = iter->left;
+ swap_entry = iter->entry;
+ iter->entry = swap_iter->entry;
+ swap_iter->entry = swap_entry;
+
+ /* Reformat the tree links */
+ iter->left = swap_iter->left;
+ swap_iter->left = swap_iter->right;
+ swap_iter->right = iter->right;
+ iter->right = swap_iter;
+
+ /* Fix the balance values
+ *
+ * if B < 0
+ * A = A + 1 - B
+ * else
+ * A = A + 1
+ *
+ * diff = A + 1 - B
+ * if diff > 0
+ * B = B + 1 + diff
+ * else
+ * B = B + 1
+ */
+ swap_balance = swap_iter->balance;
+ swap_iter->balance = iter->balance + 1;
+ if ( 0 > swap_balance )
+ {
+ swap_iter->balance -= swap_balance;
+ }
+ iter->balance = iter->balance + 1 - swap_balance;
+ if ( 0 > iter->balance )
+ {
+ iter->balance = 0;
+ }
+ iter->balance += swap_balance + 1;
+
+ /* We added a child so our depth was increased, but we also saved depth by rotation so our parents depth stays the same */
+ if ( 0 > swap_balance )
+ {
+ break;
+ }
+ }
+
+ /* Store ourself in new_entry for the check in the next parent */
+ new_entry = iter;
+ }
+
return list;
}
diff --git a/libsqueeze/btree.h b/libsqueeze/btree.h
index 67a067b..a7bc8d7 100644
--- a/libsqueeze/btree.h
+++ b/libsqueeze/btree.h
@@ -24,6 +24,7 @@ struct _LSQBTree {
LSQBTree *next;
LSQBTree *left;
LSQBTree *right;
+ gint balance;
};
LSQBTree *
More information about the Xfce4-commits
mailing list