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); } }
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); }
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); }
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); }
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); }
/* 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); }
/* 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); }