/** * Add an entry node. * * \param selected add the entry in the currently-selected node */ void hotlist_add_entry(bool selected) { struct node *node; struct node *parent = NULL; creating_node = true; if (selected == true) { parent = tree_get_selected_node(tree_get_root(hotlist_tree)); if (parent && (tree_node_is_folder(parent) == false)) { parent = tree_node_get_parent(parent); } } if (parent == NULL) { parent = tree_get_default_folder_node(hotlist_tree); } node = tree_create_URL_node(hotlist_tree, parent, "Address", "Untitled", hotlist_node_callback, NULL); if (node == NULL) return; tree_set_node_user_callback(node, hotlist_node_callback, NULL); tree_url_node_edit_title(hotlist_tree, node); }
/** * Add a folder node. * * \param selected create the folder in the currently-selected node */ void hotlist_add_folder(bool selected) { struct node *node, *parent = NULL; struct node_element *element; char *title = strdup("Untitled"); if (title == NULL) { LOG(("malloc failed")); warn_user("NoMemory", 0); return; } creating_node = true; if (selected == true) { parent = tree_get_selected_node(tree_get_root(hotlist_tree)); if (parent && (tree_node_is_folder(parent) == false)) { parent = tree_node_get_parent(parent); } } if (parent == NULL) { parent = tree_get_default_folder_node(hotlist_tree); } node = tree_create_folder_node(hotlist_tree, parent, title, true, false, false); if (node == NULL) { free(title); return; } tree_set_node_user_callback(node, hotlist_node_callback, NULL); tree_set_node_icon(hotlist_tree, node, folder_icon); element = tree_node_find_element(node, TREE_ELEMENT_TITLE, NULL); tree_start_edit(hotlist_tree, element); }
TreeNode *_bin_tree_successor (TreeNode *n, TreeNode *sent) { TreeNode *r; TreeNode *y; if ((r = tree_node_get_right (n)) != sent) { return (_bin_tree_minimum (r, sent)); } y = tree_node_get_parent (n); while ((y != sent) && (n == tree_node_get_right (y))) { n = y; y = tree_node_get_parent (y); } return y; }
TreeNode *_bin_tree_predecessor (TreeNode *n, TreeNode *sent) { TreeNode *l; TreeNode *y; if ((l = tree_node_get_left (n)) != sent) { return (_bin_tree_maximum (l, sent)); } y = tree_node_get_parent (n); while ((y != sent) && (n == tree_node_get_left (y))) { n = y; y = tree_node_get_parent (y); } return y; }
static void right_rotate (RbTree *t, TreeNode *x) { TreeNode *y; TreeNode *ry; TreeNode *px; assert (t != NULL); assert (x != NULL); /* Set y */ y = tree_node_get_left (x); assert (y != NULL); /* Turn y's right subtree into x's left subtree */ ry = tree_node_get_right (y); tree_node_set_left (x, ry); if (ry != t->sent) { tree_node_set_parent (ry, x); } /* Link x's parent to y */ px = tree_node_get_parent (x); tree_node_set_parent (y, px); if (px == t->sent) { tree_node_set_right (t->sent, y); } else { if (x == tree_node_get_left (px)) { tree_node_set_left (px, y); } else /* x == tree_node_get_right (px) */ { tree_node_set_right (px, y); } } /* Put x on y's right */ tree_node_set_right (y, x); tree_node_set_parent (x, y); }
static void rb_delete_fixup (RbTree *t, TreeNode *x) { TreeNode *px; /* x's parent */ TreeNode *w; /* x's brother */ TreeNode *lw; TreeNode *rw; TreeNode *root; root = tree_node_get_right (t->sent); while ((x != root) && tree_node_is_black (x)) { /* x is DOUBLE-BLACK now */ px = tree_node_get_parent (x); if (x == tree_node_get_left (px)) { w = tree_node_get_right (px); if (tree_node_is_red (w)) { tree_node_set_black (w); tree_node_set_red (px); left_rotate (t, px); w = tree_node_get_right (px); } lw = tree_node_get_left (w); rw = tree_node_get_right (w); if (tree_node_is_black (lw) && tree_node_is_black (rw)) /* both child are black, so w can be red */ { tree_node_set_red (w); x = px; } else /* one child or none are black, at least one is red */ { if (tree_node_is_black (rw)) /* so that lw is red */ { tree_node_set_black (lw); tree_node_set_red (w); right_rotate (t, w); w = tree_node_get_right (px); lw = tree_node_get_left (w); rw = tree_node_get_right (rw); } /* now rw is red */ tree_node_is_red (px) ? tree_node_set_red (w) : tree_node_set_black (w); tree_node_set_black (px); tree_node_set_black (rw); left_rotate (t, px); x = root; } } else /* x == tree_node_get_right (px) */ { w = tree_node_get_left (px); if (tree_node_is_red (w)) { tree_node_set_black (w); tree_node_set_red (px); right_rotate (t, px); w = tree_node_get_left (px); } lw = tree_node_get_left (w); rw = tree_node_get_right (w); if (tree_node_is_black (lw) && tree_node_is_black (rw)) { tree_node_set_red (w); x = px; } else /* one child or none are black, at least one is red */ { if (tree_node_is_black (lw)) { tree_node_set_black (rw); tree_node_set_red (w); left_rotate (t, w); w = tree_node_get_left (px); lw = tree_node_get_left (w); rw = tree_node_get_right (w); } /* now lw is red */ tree_node_is_red (px) ? tree_node_set_red (w) : tree_node_set_black (w); tree_node_set_black (px); tree_node_set_black (lw); right_rotate (t, px); x = root; } } } tree_node_set_black (x); }
static void rb_insert_fixup (RbTree *t, TreeNode *z) { TreeNode *y; /* z's uncle */ TreeNode *pz; /* z's parent */ TreeNode *ppz; /* z's parent's parent */ static int i = 0; i++; while (tree_node_is_red (tree_node_get_parent (z))) /* so that p[p[z]] is black */ { pz = tree_node_get_parent (z); ppz = tree_node_get_parent (pz); if (pz == tree_node_get_left (ppz)) { y = tree_node_get_right (ppz); if (tree_node_is_red (y)) { tree_node_set_black (pz); tree_node_set_black (y); tree_node_set_red (ppz); z = ppz; } else /* tree_node_is_black (y) */ { if (z == tree_node_get_right (pz)) { z = pz; left_rotate (t, z); } /* take care, z may has been changed */ pz = tree_node_get_parent (z); ppz = tree_node_get_parent (pz); tree_node_set_black (pz); tree_node_set_red (ppz); right_rotate (t, ppz); } } else /* pz == tree_node_get_right (ppz) */ { y = tree_node_get_left (ppz); if (tree_node_is_red (y)) { tree_node_set_black (pz); tree_node_set_black (y); tree_node_set_red (ppz); z = ppz; } else /* tree_node_is_black (y) */ { if (z == tree_node_get_left (pz)) { z = pz; right_rotate (t, z); pz = tree_node_get_parent (z); ppz = tree_node_get_parent (pz); } tree_node_set_black (pz); tree_node_set_red (ppz); left_rotate (t, ppz); } } } tree_node_set_black (tree_node_get_right (t->sent)); }
void *rb_tree_delete (RbTree *t, void *data) { TreeNode *x; /* y's not SENTINEL child, or SENTINEL if y don't have child */ TreeNode *y; /* the node actually delete */ TreeNode *z; /* the node contain data */ TreeNode *py; /* parent of y */ assert (t != NULL); z = _bin_tree_search (tree_node_get_right (t->sent), t->sent, t->cmp_f, data); if (z == NULL) { fprintf (stderr, "warning!, return an NULL\n"); return NULL; } if ((tree_node_get_left (z) == t->sent) || (tree_node_get_right (z) == t->sent)) { y = z; } else { y = _bin_tree_successor (z, t->sent); } if (tree_node_get_left (y) != t->sent) { x = tree_node_get_left (y); } else { x = tree_node_get_right (y); } py = tree_node_get_parent (y); tree_node_set_parent (x, py); if (py == t->sent) { tree_node_set_right (t->sent, x); } else { if (y == tree_node_get_left (py)) { tree_node_set_left (py, x); } else { tree_node_set_right (py, x); } } if (y != z) { tree_node_set_content (z, tree_node_get_content (y)); } if (tree_node_is_black (y)) { rb_delete_fixup (t, x); } tree_node_free (y); (t->card)--; return data; }