Exemple #1
0
void
_gtk_rbtree_next_full (GtkRBTree  *tree,
		       GtkRBNode  *node,
		       GtkRBTree **new_tree,
		       GtkRBNode **new_node)
{
  g_return_if_fail (tree != NULL);
  g_return_if_fail (node != NULL);
  g_return_if_fail (new_tree != NULL);
  g_return_if_fail (new_node != NULL);

  if (node->children)
    {
      *new_tree = node->children;
      *new_node = (*new_tree)->root;
      while (!_gtk_rbtree_is_nil ((*new_node)->left))
	*new_node = (*new_node)->left;
      return;
    }

  *new_tree = tree;
  *new_node = _gtk_rbtree_next (tree, node);

  while ((*new_node == NULL) &&
	 (*new_tree != NULL))
    {
      *new_node = (*new_tree)->parent_node;
      *new_tree = (*new_tree)->parent_tree;
      if (*new_tree)
	*new_node = _gtk_rbtree_next (*new_tree, *new_node);
    }
}
Exemple #2
0
static void
test_reorder (void)
{
  guint n = g_test_perf () ? 1000000 : 100;
  GtkRBTree *tree;
  GtkRBNode *node;
  gint *reorder;
  guint i;
  double elapsed;

  reorder = fisher_yates_shuffle (n);
  tree = create_unsorted_tree (reorder, n);

  g_test_timer_start ();

  _gtk_rbtree_reorder (tree, reorder, n);

  elapsed = g_test_timer_elapsed ();
  if (g_test_perf ())
    g_test_minimized_result (elapsed, "reordering rbtree with %u items: %gsec", n, elapsed);

  _gtk_rbtree_test (tree);

  for (node = _gtk_rbtree_first (tree), i = 0;
       node != NULL;
       node = _gtk_rbtree_next (tree, node), i++)
    {
      g_assert (GTK_RBNODE_GET_HEIGHT (node) == i);
    }
  g_assert (i == n);

  _gtk_rbtree_free (tree);
}
Exemple #3
0
void
_gtk_rbtree_set_fixed_height (GtkRBTree *tree,
			      gint       height,
			      gboolean   mark_valid)
{
  GtkRBNode *node;

  if (tree == NULL)
    return;

  node = _gtk_rbtree_first (tree);

  do
    {
      if (GTK_RBNODE_FLAG_SET (node, GTK_RBNODE_INVALID))
        {
	  _gtk_rbtree_node_set_height (tree, node, height);
	  if (mark_valid)
	    _gtk_rbtree_node_mark_valid (tree, node);
	}

      if (node->children)
	_gtk_rbtree_set_fixed_height (node->children, height, mark_valid);
    }
  while ((node = _gtk_rbtree_next (tree, node)) != NULL);
}
Exemple #4
0
void
_gtk_rbtree_mark_invalid (GtkRBTree *tree)
{
  GtkRBNode *node;

  if (tree == NULL)
    return;

  node = _gtk_rbtree_first (tree);

  do
    {
      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_INVALID);
      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);

      if (node->children)
	_gtk_rbtree_mark_invalid (node->children);
    }
  while ((node = _gtk_rbtree_next (tree, node)) != NULL);
}
Exemple #5
0
void
_gtk_rbtree_mark_invalid (GtkRBTree *tree)
{
  GtkRBNode *node;

  if (tree == NULL)
    return;
  node = tree->root;
  g_assert (node);

  while (node->left != tree->nil)
    node = node->left;

  do
    {
      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_INVALID);
      GTK_RBNODE_SET_FLAG (node, GTK_RBNODE_DESCENDANTS_INVALID);

      if (node->children)
	_gtk_rbtree_mark_invalid (node->children);
    }
  while ((node = _gtk_rbtree_next (tree, node)) != NULL);
}
Exemple #6
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)
{
  GtkRBNode **nodes;
  GtkRBNode *node;
  gint i, j;
  
  g_return_if_fail (tree != NULL);
  g_return_if_fail (length > 0);
  g_return_if_fail (tree->root->count == length);
  
  nodes = g_new (GtkRBNode *, length);

  _gtk_rbtree_traverse (tree, tree->root, G_PRE_ORDER, reorder_prepare, NULL);

  for (node = _gtk_rbtree_first (tree), i = 0;
       node;
       node = _gtk_rbtree_next (tree, node), i++)
    {
      nodes[i] = node;
    }

  for (i = 0; i < length; i++)
    {
      GtkRBNode tmp = { 0, };
      GSList *l, *cycle = NULL;

      tmp.offset = -1;

      /* already swapped */
      if (nodes[i] == NULL)
        continue;
      /* no need to swap */
      if (new_order[i] == i)
        continue;

      /* make a list out of the pending nodes */
      for (j = i; new_order[j] != i; j = new_order[j])
        {
          cycle = g_slist_prepend (cycle, nodes[j]);
          nodes[j] = NULL;
        }

      node = nodes[j];
      reorder_copy_node (tree, &tmp, node);
      for (l = cycle; l; l = l->next)
        {
          reorder_copy_node (tree, node, l->data);
          node = l->data;
        }

      reorder_copy_node (tree, node, &tmp);
      nodes[j] = NULL;
      g_slist_free (cycle);
    }

  _gtk_rbtree_traverse (tree, tree->root, G_POST_ORDER, reorder_fixup, NULL);

  g_free (nodes);
}
Exemple #7
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);
}