// Search for the parent of an item in the tree (recursively) node_t *search_parent(node_t **tree, node_t *parent, int data, compare_t compare) { // Is the tree empty? if(*tree == NULL) { // The node is not in the tree, hence no parent return NULL; } // The tree is not empty else { // Compare against the current node int result = compare(*tree, data); if(result < 0) { // Recurse into the left sub-tree return search_parent(&(*tree)->left, *tree, data, compare); } else if(result > 0) { // Recurse into the right sub-tree return search_parent(&(*tree)->right, *tree, data, compare); } else { // Found the item, return the parent return parent; } } }
std::pair<Node *, Direction> BinTree::search_parent(int x, Node * nd) { if ( nd->left and nd->left->val == x ) return std::make_pair(nd, Direction::left); if ( nd->right and nd->right->val == x ) return std::make_pair(nd, Direction::right); if ( nd->val < x ) return nd->right ? search_parent(x, nd->right) : std::make_pair(nullptr, Direction::left); if ( nd->val > x ) return nd->left ? search_parent(x, nd->left) : std::make_pair(nullptr, Direction::left); std::cerr << "Parent not found\n"; return std::make_pair(nullptr, Direction::left); }
NODE *search_parent (NODE *node, int key) { if (node->left->data == key) return node; if (node->right->data == key) return node; if (key < node->data) search_parent(node->left, key); else search_parent(node->right, key); }
bool delete_bst(node_pointer_t root, int data) { node_pointer_t tmp_node = NULL; node_pointer_t pre_node = NULL; node_pointer_t max_node = NULL; tmp_node = search_bst(root, data); pre_node = search_parent(root, data); if(tmp_node->rchild&&tmp_node->lchild) { pre_node = tmp_node; max_node = tmp_node->lchild; while(max_node->rchild) { pre_node = max_node; max_node = max_node->rchild; } tmp_node->data = max_node->data; if(pre_node->rchild->data == max_node->data) pre_node->rchild = max_node->lchild; else pre_node->lchild = max_node->lchild; free(max_node); } else if((max_node = tmp_node->rchild)||(max_node = tmp_node->lchild)) { if(pre_node->rchild&&pre_node->rchild->data == data) pre_node->rchild = max_node; else pre_node->lchild = max_node; free(tmp_node); } else { if(pre_node->rchild&&pre_node->rchild->data == data) pre_node->rchild = NULL; else pre_node->lchild = NULL; free(tmp_node); } return true; }
void BinTree::rotate(int x, Direction d) { Node* Node::* dp = (d == Direction::left ? &Node::left : &Node::right), * Node::*ndp = (dp == &Node::left ? &Node::right : &Node::left); Node * nd = search(x); if (nd==nullptr) return; Node * pivot = nd->*dp, * prev_root = nd, * pivot_chld = pivot->*ndp; if (nd == root) { root = pivot; prev_root->*dp = pivot_chld; pivot->*ndp = prev_root; } else { nd = pivot; std::pair<Node *, Direction> parroot = search_parent(x,root); parroot.first->*(parroot.second == Direction::left ? &Node::left : &Node::right) = pivot; prev_root->*dp = pivot_chld; pivot->*ndp = prev_root; } }
bool insert_bst(node_pointer_t *root, int data) { node_pointer_t tmp_node = NULL; node_pointer_t new_node = NULL; tmp_node = search_bst(*root, data); if(tmp_node) { fprintf(stderr, " ERROR: same data already exist\n"); return false; } new_node = get_new_node(data); if(!new_node) { fprintf(stderr, " ERROR: memory is full\n"); return false; } if(!*root) { *root = new_node; return true; } tmp_node = search_parent(*root, data); if(tmp_node->data < data) tmp_node->rchild = new_node; else if(tmp_node->data > data) tmp_node->lchild = new_node; return true; }
/* The up-down function will chech too much halfspaces when the tree root and the target point * are too far away. Thus the search function below which start from the target parent and * move up in the tree - down-up search. * It uses the Parent link and goes up until the target is closed from all sides with large enough * hyperrectangle, or if the tree root is reached */ KDTEMPLATE KDNODE* KDTREE::find_nearest(const T *point) { if (!root) return NULL; checked_nodes = 0; KDNODE* parent = root->FindParent(point); nearest_neighbour = parent; d_min = distance2(point, parent->pt); if (equal(point, parent->pt)) return nearest_neighbour; #ifdef UP_DOWN_SEARCH check_subtree(root, point); #else search_parent(parent, point); uncheck(); #endif // !UP_DOWN_SEARCH return nearest_neighbour; }
parent->right = NULL; } else { printf("Not a child of the parent: data = %d, child = %p\n", child->data, child); } } return detached; } // Delete an item in the tree void delete(node_t **tree, int data, compare_t compare) { // Find the node and its parent node_t *node = search(tree, data, compare); node_t *parent = search_parent(tree, NULL, data, compare); if((node != NULL) && (parent != NULL)) { // Get the parent's link to the node node_t **link = (node == parent->left) ? &parent->left : &parent->right; // If the node has no right sub-tree? if(node->right == NULL) { // If the node has no left sub-tree? if(node->left == NULL) { // Node has no left or right sub-tree, so can be simply deleted printf("\nNo L, no R: delete item %d at %p\n", node->data, node); *link = NULL; free(node); }
void BinTree::delnode(int x) { Node* nd = search(x,root); if (nd == nullptr) return; std::pair<Node *, Direction> par = search_parent(x,root); auto dir = par.second==Direction::left ? &Node::left : &Node::right; auto erase_child_with_1_child = [](std::pair<Node *, Direction> par, Direction nd_ch) { auto dir = par.second==Direction::right ? &Node::right : &Node::left, counterdir = dir==&Node::right ? &Node::left : &Node::right; Node * tmp = par.first->*dir; par.first->*dir = (par.first->*dir)->*counterdir; tmp->*counterdir=nullptr; delete tmp; }; if (nd->left==nullptr and nd->right==nullptr) { if (par.first != nullptr) par.first->*dir=nullptr; delete nd; if(nd == root) root = nullptr; nd = nullptr; } else if (nd->left==nullptr) { if(par.first == nullptr) { Node*tmp = nd; root = nd->right; tmp->right = nullptr; delete tmp; return; } erase_child_with_1_child(par, Direction::right); } else if (nd->right==nullptr) { if(par.first == nullptr) { Node*tmp = nd; root = nd->left; tmp->left = nullptr; delete tmp; return; } erase_child_with_1_child(par, Direction::left); } else { Node * minr = search_min_right(nd->right); if (minr == nd->right) { nd->val= nd->right->val; erase_child_with_1_child (std::make_pair(nd, Direction::right), Direction::right); return; } nd->val=minr->val; auto minr_par = search_parent(minr->val, nd->right); minr_par.first->left=minr->right; minr->right=nullptr; delete minr; } }