Exemplo n.º 1
0
static void
gtk_rbtree_print_node (GtkRBTree *tree,
                       GtkRBNode *node,
                       gint       depth)
{
  gint i;
  for (i = 0; i < depth; i++)
    g_print ("\t");

  g_print ("(%p - %s) (Offset %d) (Parity %d) (Validity %d%d%d)\n",
	   node,
	   (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)?"BLACK":" RED ",
	   node->offset,
	   node->total_count,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))?1:0);
  if (node->children != NULL)
    {
      g_print ("Looking at child.\n");
      gtk_rbtree_print_node (node->children, node->children->root, depth + 1);
      g_print ("Done looking at child.\n");
    }
  if (!_gtk_rbtree_is_nil (node->left))
    {
      gtk_rbtree_print_node (tree, node->left, depth+1);
    }
  if (!_gtk_rbtree_is_nil (node->right))
    {
      gtk_rbtree_print_node (tree, node->right, depth+1);
    }
}
Exemplo n.º 2
0
static void
_gtk_rbtree_debug_spew_helper (GtkRBTree *tree,
			       GtkRBNode *node,
                               GString   *s,
			       gint       depth)
{
  gint i;
  for (i = 0; i < depth; i++)
    g_string_append (s, "\t");

  g_string_append_printf (s, "(%p - %s) (Offset %d) (Parity %d) (Validity %d%d%d)\n",
	   node,
	   (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)?"BLACK":" RED ",
	   node->offset,
	   node->total_count,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))?1:0);
  if (node->children != NULL)
    {
      g_string_append (s, "Looking at child.\n");
      _gtk_rbtree_debug_spew (node->children, s);
      g_string_append (s, "Done looking at child.\n");
    }
  if (!_gtk_rbtree_is_nil (node->left))
    {
      _gtk_rbtree_debug_spew_helper (tree, node->left, s, depth + 1);
    }
  if (!_gtk_rbtree_is_nil (node->right))
    {
      _gtk_rbtree_debug_spew_helper (tree, node->right, s, depth + 1);
    }
}
Exemplo n.º 3
0
static void
_gtk_rbtree_debug_spew_helper (GtkRBTree *tree,
			       GtkRBNode *node,
			       gint       depth)
{
  gint i;
  for (i = 0; i < depth; i++)
    g_print ("\t");

  g_print ("(%p - %s) (Offset %d) (Parity %d) (Validity %d%d%d)\n",
	   node,
	   (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)?"BLACK":" RED ",
	   node->offset,
	   node->parity?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_DESCENDANTS_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))?1:0,
	   (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_COLUMN_INVALID))?1:0);
  if (node->children != NULL)
    {
      g_print ("Looking at child.\n");
      _gtk_rbtree_debug_spew (node->children);
      g_print ("Done looking at child.\n");
    }
  if (node->left != tree->nil)
    {
      _gtk_rbtree_debug_spew_helper (tree, node->left, depth+1);
    }
  if (node->right != tree->nil)
    {
      _gtk_rbtree_debug_spew_helper (tree, node->right, depth+1);
    }
}
Exemplo n.º 4
0
static guint
_gtk_rbtree_test_structure_helper (GtkRBTree *tree,
				   GtkRBNode *node)
{
  guint left_blacks, right_blacks;

  g_assert (!_gtk_rbtree_is_nil (node));

  g_assert (node->left != NULL);
  g_assert (node->right != NULL);
  g_assert (node->parent != NULL);

  if (!_gtk_rbtree_is_nil (node->left))
    {
      g_assert (node->left->parent == node);
      left_blacks = _gtk_rbtree_test_structure_helper (tree, node->left);
    }
  else
    left_blacks = 0;

  if (!_gtk_rbtree_is_nil (node->right))
    {
      g_assert (node->right->parent == node);
      right_blacks = _gtk_rbtree_test_structure_helper (tree, node->right);
    }
  else
    right_blacks = 0;

  if (node->children != NULL)
    {
      g_assert (node->children->parent_tree == tree);
      g_assert (node->children->parent_node == node);

      _gtk_rbtree_test_structure (node->children);
    }

  g_assert (left_blacks == right_blacks);

  return left_blacks + (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK ? 1 : 0);
}
Exemplo n.º 5
0
static void
reorder_copy_node (GtkRBTree *tree,
                   GtkRBNode *to,
                   GtkRBNode *from)
{
  to->flags = (to->flags & GTK_RBNODE_NON_COLORS) | GTK_RBNODE_GET_COLOR (from);

  to->left = from->left;
  if (!_gtk_rbtree_is_nil (to->left))
    to->left->parent = to;

  to->right = from->right;
  if (!_gtk_rbtree_is_nil (to->right))
    to->right->parent = to;

  to->parent = from->parent;
  if (_gtk_rbtree_is_nil (to->parent))
    tree->root = to;
  else if (to->parent->left == from)
    to->parent->left = to;
  else if (to->parent->right == from)
    to->parent->right = to;
}
Exemplo n.º 6
0
static void
_gtk_rbtree_remove_node_fixup (GtkRBTree *tree,
			       GtkRBNode *node,
                               GtkRBNode *parent)
{
  while (node != tree->root && GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
    {
      if (node == parent->left)
	{
	  GtkRBNode *w = parent->right;
	  if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
	    {
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (parent, GTK_RBNODE_RED);
	      _gtk_rbnode_rotate_left (tree, parent);
	      w = parent->right;
	    }
	  if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
	    {
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
	      node = parent;
	    }
	  else
	    {
	      if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK)
		{
		  GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
		  GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
		  _gtk_rbnode_rotate_right (tree, w);
		  w = parent->right;
		}
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (parent));
	      GTK_RBNODE_SET_COLOR (parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
	      _gtk_rbnode_rotate_left (tree, parent);
	      node = tree->root;
	    }
	}
      else
	{
	  GtkRBNode *w = parent->left;
	  if (GTK_RBNODE_GET_COLOR (w) == GTK_RBNODE_RED)
	    {
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (parent, GTK_RBNODE_RED);
	      _gtk_rbnode_rotate_right (tree, parent);
	      w = parent->left;
	    }
	  if (GTK_RBNODE_GET_COLOR (w->right) == GTK_RBNODE_BLACK && GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
	    {
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
	      node = parent;
	    }
	  else
	    {
	      if (GTK_RBNODE_GET_COLOR (w->left) == GTK_RBNODE_BLACK)
		{
		  GTK_RBNODE_SET_COLOR (w->right, GTK_RBNODE_BLACK);
		  GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_RED);
		  _gtk_rbnode_rotate_left (tree, w);
		  w = parent->left;
		}
	      GTK_RBNODE_SET_COLOR (w, GTK_RBNODE_GET_COLOR (parent));
	      GTK_RBNODE_SET_COLOR (parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (w->left, GTK_RBNODE_BLACK);
	      _gtk_rbnode_rotate_right (tree, parent);
	      node = tree->root;
	    }
	}

      parent = node->parent;
    }
  GTK_RBNODE_SET_COLOR (node, GTK_RBNODE_BLACK);
}
Exemplo n.º 7
0
static void
_gtk_rbtree_insert_fixup (GtkRBTree *tree,
			  GtkRBNode *node)
{

  /* check Red-Black properties */
  while (node != tree->root && GTK_RBNODE_GET_COLOR (node->parent) == GTK_RBNODE_RED)
    {
      /* we have a violation */
      if (node->parent == node->parent->parent->left)
	{
	  GtkRBNode *y = node->parent->parent->right;
	  if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
	    {
				/* uncle is GTK_RBNODE_RED */
	      GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
	      node = node->parent->parent;
	    }
	  else
	    {
				/* uncle is GTK_RBNODE_BLACK */
	      if (node == node->parent->right)
		{
		  /* make node a left child */
		  node = node->parent;
		  _gtk_rbnode_rotate_left (tree, node);
		}

				/* recolor and rotate */
	      GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
	      _gtk_rbnode_rotate_right(tree, node->parent->parent);
	    }
	}
      else
	{
	  /* mirror image of above code */
	  GtkRBNode *y = node->parent->parent->left;
	  if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_RED)
	    {
				/* uncle is GTK_RBNODE_RED */
	      GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (y, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
	      node = node->parent->parent;
	    }
	  else
	    {
				/* uncle is GTK_RBNODE_BLACK */
	      if (node == node->parent->left)
		{
		  node = node->parent;
		  _gtk_rbnode_rotate_right (tree, node);
		}
	      GTK_RBNODE_SET_COLOR (node->parent, GTK_RBNODE_BLACK);
	      GTK_RBNODE_SET_COLOR (node->parent->parent, GTK_RBNODE_RED);
	      _gtk_rbnode_rotate_left (tree, node->parent->parent);
	    }
	}
    }
  GTK_RBNODE_SET_COLOR (tree->root, GTK_RBNODE_BLACK);
}
Exemplo n.º 8
0
void
_gtk_rbtree_remove_node (GtkRBTree *tree,
			 GtkRBNode *node)
{
  GtkRBNode *x, *y;
  gint y_height;
  guint y_total_count;
  
  g_return_if_fail (tree != NULL);
  g_return_if_fail (node != NULL);

  
#ifdef G_ENABLE_DEBUG
  if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
    {
      g_print ("\n\n_gtk_rbtree_remove_node: %p\n", node);
      _gtk_rbtree_debug_spew (tree);
      _gtk_rbtree_test (G_STRLOC, tree);
    }
#endif /* G_ENABLE_DEBUG */
  
  /* make sure we're deleting a node that's actually in the tree */
  for (x = node; !_gtk_rbtree_is_nil (x->parent); x = x->parent)
    ;
  g_return_if_fail (x == tree->root);

#ifdef G_ENABLE_DEBUG  
  if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
    _gtk_rbtree_test (G_STRLOC, tree);
#endif
  
  if (_gtk_rbtree_is_nil (node->left) ||
      _gtk_rbtree_is_nil (node->right))
    {
      y = node;
    }
  else
    {
      y = node->right;

      while (!_gtk_rbtree_is_nil (y->left))
	y = y->left;
    }

  y_height = GTK_RBNODE_GET_HEIGHT (y) 
             + (y->children ? y->children->root->offset : 0);
  y_total_count = 1 + (y->children ? y->children->root->total_count : 0);

  /* x is y's only child, or nil */
  if (!_gtk_rbtree_is_nil (y->left))
    x = y->left;
  else
    x = y->right;

  /* remove y from the parent chain */
  if (!_gtk_rbtree_is_nil (x))
    x->parent = y->parent;
  if (!_gtk_rbtree_is_nil (y->parent))
    {
      if (y == y->parent->left)
	y->parent->left = x;
      else
	y->parent->right = x;
    }
  else
    {
      tree->root = x;
    }

  /* We need to clean up the validity of the tree.
   */
  gtk_rbnode_adjust (tree, y, -1, - y_total_count, - y_height);

  if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
    _gtk_rbtree_remove_node_fixup (tree, x, y->parent);

  if (y != node)
    {
      gint node_height, node_total_count;

      /* We want to see how much we remove from the aggregate values.
       * This is all the children we remove plus the node's values.
       */
      node_height = GTK_RBNODE_GET_HEIGHT (node)
                    + (node->children ? node->children->root->offset : 0);
      node_total_count = 1
                         + (node->children ? node->children->root->total_count : 0);

      /* Move the node over */
      if (GTK_RBNODE_GET_COLOR (node) != GTK_RBNODE_GET_COLOR (y))
	y->flags ^= (GTK_RBNODE_BLACK | GTK_RBNODE_RED);

      y->left = node->left;
      if (!_gtk_rbtree_is_nil (y->left))
        y->left->parent = y;
      y->right = node->right;
      if (!_gtk_rbtree_is_nil (y->right))
        y->right->parent = y;
      y->parent = node->parent;
      if (!_gtk_rbtree_is_nil (y->parent))
        {
          if (y->parent->left == node)
            y->parent->left = y;
          else
            y->parent->right = y;
        }
      else
        {
          tree->root = y;
        }
      y->count = node->count;
      y->total_count = node->total_count;
      y->offset = node->offset;

      gtk_rbnode_adjust (tree, y, 
                         0,
                         y_total_count - node_total_count,
                         y_height - node_height);
    }

  _gtk_rbnode_free (node);

#ifdef G_ENABLE_DEBUG  
  if (gtk_get_debug_flags () & GTK_DEBUG_TREE)
    {
      g_print ("_gtk_rbtree_remove_node finished...\n");
      _gtk_rbtree_debug_spew (tree);
      g_print ("\n\n");
      _gtk_rbtree_test (G_STRLOC, tree);
    }
#endif /* G_ENABLE_DEBUG */  
}
Exemplo n.º 9
0
/* It basically pulls everything out of the tree, rearranges it, and puts it
 * back together.  Our strategy is to keep the old RBTree intact, and just
 * rearrange the contents.  When that is done, we go through and update the
 * heights.  There is probably a more elegant way to write this function.  If
 * anyone wants to spend the time writing it, patches will be accepted.
 */
void
_gtk_rbtree_reorder (GtkRBTree *tree,
		     gint      *new_order,
		     gint       length)
{
  GtkRBReorder reorder = { NULL };
  GArray *array;
  GtkRBNode *node;
  gint i;
  
  g_return_if_fail (tree != NULL);
  g_return_if_fail (length > 0);
  g_return_if_fail (tree->root->count == length);
  
  /* Sort the trees values in the new tree. */
  array = g_array_sized_new (FALSE, FALSE, sizeof (GtkRBReorder), length);
  for (i = 0; i < length; i++)
    {
      reorder.order = new_order[i];
      reorder.invert_order = i;
      g_array_append_val (array, reorder);
    }

  g_array_sort(array, gtk_rbtree_reorder_sort_func);

  /* rewind node*/
  node = tree->root;
  while (node && node->left != tree->nil)
    node = node->left;

  for (i = 0; i < length; i++)
    {
      g_assert (node != tree->nil);
      g_array_index (array, GtkRBReorder, i).children = node->children;
      g_array_index (array, GtkRBReorder, i).flags = GTK_RBNODE_NON_COLORS & node->flags;
      g_array_index (array, GtkRBReorder, i).height = GTK_RBNODE_GET_HEIGHT (node);

      node = _gtk_rbtree_next (tree, node);
    }

  g_array_sort (array, gtk_rbtree_reorder_invert_func);
 
  /* rewind node*/
  node = tree->root;
  while (node && node->left != tree->nil)
    node = node->left;

  /* Go through the tree and change the values to the new ones. */
  for (i = 0; i < length; i++)
    {
      reorder = g_array_index (array, GtkRBReorder, i);
      node->children = reorder.children;
      if (node->children)
	node->children->parent_node = node;
      node->flags = GTK_RBNODE_GET_COLOR (node) | reorder.flags;
      /* We temporarily set the height to this. */
      node->offset = reorder.height;
      node = _gtk_rbtree_next (tree, node);
    }
  gtk_rbtree_reorder_fixup (tree, tree->root);

  g_array_free (array, TRUE);
}
Exemplo n.º 10
0
void
_gtk_rbtree_remove_node (GtkRBTree *tree,
			 GtkRBNode *node)
{
  GtkRBNode *x, *y;
  GtkRBTree *tmp_tree;
  GtkRBNode *tmp_node;
  gint y_height;
  
  g_return_if_fail (tree != NULL);
  g_return_if_fail (node != NULL);

  
#ifdef G_ENABLE_DEBUG
  if (gtk_debug_flags & GTK_DEBUG_TREE)
    {
      g_print ("\n\n_gtk_rbtree_remove_node: %p\n", node);
      _gtk_rbtree_debug_spew (tree);
      _gtk_rbtree_test (G_STRLOC, tree);
    }
#endif /* G_ENABLE_DEBUG */
  
  /* make sure we're deleting a node that's actually in the tree */
  for (x = node; x->parent != tree->nil; x = x->parent)
    ;
  g_return_if_fail (x == tree->root);

#ifdef G_ENABLE_DEBUG  
  if (gtk_debug_flags & GTK_DEBUG_TREE)
    _gtk_rbtree_test (G_STRLOC, tree);
#endif
  
  if (node->left == tree->nil || node->right == tree->nil)
    {
      y = node;
    }
  else
    {
      y = node->right;

      while (y->left != tree->nil)
	y = y->left;
    }

  /* adjust count only beneath tree */
  for (x = y; x != tree->nil; x = x->parent)
    {
      x->count--;
    }

  /* offsets and parity adjust all the way up through parent trees */
  y_height = GTK_RBNODE_GET_HEIGHT (y);

  tmp_tree = tree;
  tmp_node = y;
  while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
    {
      tmp_node->offset -= (y_height + (y->children?y->children->root->offset:0));
      _fixup_validation (tmp_tree, tmp_node);
      _fixup_parity (tmp_tree, tmp_node);
      tmp_node = tmp_node->parent;
      if (tmp_node == tmp_tree->nil)
	{
	  tmp_node = tmp_tree->parent_node;
	  tmp_tree = tmp_tree->parent_tree;
	}
    }

  /* x is y's only child, or nil */
  if (y->left != tree->nil)
    x = y->left;
  else
    x = y->right;

  /* remove y from the parent chain */
  x->parent = y->parent;
  if (y->parent != tree->nil)
    {
      if (y == y->parent->left)
	y->parent->left = x;
      else
	y->parent->right = x;
    }
  else
    {
      tree->root = x;
    }

  /* We need to clean up the validity of the tree.
   */

  tmp_tree = tree;
  tmp_node = x;
  do
    {
      /* We skip the first time, iff x is nil */
      if (tmp_node != tmp_tree->nil)
	{
	  _fixup_validation (tmp_tree, tmp_node);
	  _fixup_parity (tmp_tree, tmp_node);
	}
      tmp_node = tmp_node->parent;
      if (tmp_node == tmp_tree->nil)
	{
	  tmp_node = tmp_tree->parent_node;
	  tmp_tree = tmp_tree->parent_tree;
	}
    }
  while (tmp_tree != NULL);

  if (y != node)
    {
      gint diff;

      /* Copy the node over */
      if (GTK_RBNODE_GET_COLOR (node) == GTK_RBNODE_BLACK)
	node->flags = ((y->flags & (GTK_RBNODE_NON_COLORS)) | GTK_RBNODE_BLACK);
      else
	node->flags = ((y->flags & (GTK_RBNODE_NON_COLORS)) | GTK_RBNODE_RED);
      node->children = y->children;
      if (y->children)
	{
	  node->children = y->children;
	  node->children->parent_node = node;
	}
      else
	{
	  node->children = NULL;
	}
      _fixup_validation (tree, node);
      _fixup_parity (tree, node);
      /* We want to see how different our height is from the previous node.
       * To do this, we compare our current height with our supposed height.
       */
      diff = y_height - GTK_RBNODE_GET_HEIGHT (node);
      tmp_tree = tree;
      tmp_node = node;

      while (tmp_tree && tmp_node && tmp_node != tmp_tree->nil)
	{
	  tmp_node->offset += diff;
	  _fixup_validation (tmp_tree, tmp_node);
	  _fixup_parity (tmp_tree, tmp_node);
	  tmp_node = tmp_node->parent;
	  if (tmp_node == tmp_tree->nil)
	    {
	      tmp_node = tmp_tree->parent_node;
	      tmp_tree = tmp_tree->parent_tree;
	    }
	}
    }

  if (GTK_RBNODE_GET_COLOR (y) == GTK_RBNODE_BLACK)
    _gtk_rbtree_remove_node_fixup (tree, x);
  _gtk_rbnode_free (y);

#ifdef G_ENABLE_DEBUG  
  if (gtk_debug_flags & GTK_DEBUG_TREE)
    {
      g_print ("_gtk_rbtree_remove_node finished...\n");
      _gtk_rbtree_debug_spew (tree);
      g_print ("\n\n");
      _gtk_rbtree_test (G_STRLOC, tree);
    }
#endif /* G_ENABLE_DEBUG */  
}