[Xfce4-commits] <squeeze:peter/btree> Optionally balance btree after remove

Peter de Ridder noreply at xfce.org
Sun Oct 9 20:24:02 CEST 2011


Updating branch refs/heads/peter/btree
         to 2f2c6178e58c4e3eb4e9a0bbaf39239fdd266fd8 (commit)
       from 1f04b35581219671f11601e0b057f0b26a636769 (commit)

commit 2f2c6178e58c4e3eb4e9a0bbaf39239fdd266fd8
Author: Peter de Ridder <peter at xfce.org>
Date:   Sun Oct 9 20:21:03 2011 +0200

    Optionally balance btree after remove

 libsqueeze/btree.c |  122 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 121 insertions(+), 1 deletions(-)

diff --git a/libsqueeze/btree.c b/libsqueeze/btree.c
index 69ab4aa..f81d098 100644
--- a/libsqueeze/btree.c
+++ b/libsqueeze/btree.c
@@ -13,6 +13,7 @@
  *  along with this program; if not, write to the Free Software
  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  */
+
 #include <config.h>
 #include <string.h>
 #include <glib.h>
@@ -247,8 +248,12 @@ lsq_btree_remove_sorted_single (
     LSQBTree *del_entry;
     LSQBTree *stack[LSQ_BTREE_MAX_DEPTH];
     guint stack_i = 0;
-    LSQBTree *swap_iter;
     gboolean short_side;
+    LSQBTree *swap_iter;
+#ifdef BALANCE_ON_REMOVE
+    LSQArchiveEntry *swap_entry;
+    gint swap_balance;
+#endif
 
     if ( NULL != found )
     {
@@ -407,7 +412,122 @@ lsq_btree_remove_sorted_single (
             /* The balance in the higher parents doesn't change when the short side changed */
             if ( FALSE != short_side )
             {
+#ifdef BALANCE_ON_REMOVE
+                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;
+
+                    /* Saved depth by rotation so our parents depth also changes */
+                    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;
+
+                    /* Saved depth by rotation so our parents depth also changes */
+                    if ( 0 <= swap_balance )
+                    {
+                        break;
+                    }
+                }
+                else
+                {
+                    break;
+                }
+#else
                 break;
+#endif
             }
 
             /* Store ourself in new_entry for the check in the next parent */


More information about the Xfce4-commits mailing list