void RBRemoveAll(struct RBTree* _Tree, void(*_Callback)(void*)) { struct RBItrStack _ItrStack[_Tree->Size]; int i = 0; memset(_ItrStack, 0, sizeof(struct RBItrStack*) * _Tree->Size); RBDepthFirst(_Tree->Table, _ItrStack); for(i = 0; i < _Tree->Size; ++i) _Callback(_ItrStack[i].Node->Data); while(_Tree->Size > 0) { RBDeleteNode(_Tree, _Tree->Table); } }
void RBIterate(struct RBTree* _Tree, int(*_Callback)(void*)) { int i = 0; int j = 0; struct RBItrStack _Stack[_Tree->Size]; struct RBItrStack _DeleteStack[_Tree->Size]; if(_Tree->Table == NULL) return; memset(_Stack, 0, sizeof(struct RBItrStack*) * _Tree->Size); memset(_DeleteStack, 0, sizeof(struct RBItrStack*) * _Tree->Size); RBDepthFirst(_Tree->Table, _Stack); for(i = 0; i < _Tree->Size; ++i) { if(_Callback(_Stack[i].Node->Data) != 0) _DeleteStack[j] = _Stack[i]; } for(i = 0; i < j; ++i) RBDeleteNode(_Tree, _DeleteStack[i].Node); }
void RBDelete(RBTree* tree, int key){ RBNode* current = tree->root; while(current != tree->nil){ if(key == current->key){ break; } if(key < current->key){ current = current->left; }else{ current = current->right; } } if(current == tree->nil){ return; } RBNode* replace = tree->nil; if(current->left == tree->nil && current->right == tree->nil){ replace = current; }else if(current->left != tree->nil){ replace = current->left; while(replace->right != tree->nil){ replace = replace->right; } }else{ replace = current->right; while(replace->left != tree->nil){ replace = replace->left; } } current->key = replace->key; current->value = replace->value; RBDeleteNode(tree, replace); }
void RBClear(struct RBTree* _Tree) { while(_Tree->Size > 0) { RBDeleteNode(_Tree, _Tree->Table); } }
void RBDelete(struct RBTree* _Tree, void* _Data) { RBDeleteNode(_Tree, RBSearchNode(_Tree, _Data)); }
void RBDeleteNode(RBTree* tree, RBNode* node){ RBNode* child = node->left == tree->nil ? node->right : node->left; //node is root, and have no child at all if(child == tree->nil && node->isBlack){ free(node); tree->root = tree->nil; return; } replace_node(tree, node, child); //if node is red, replace and free will just work if(node->isBlack){ if(!child->isBlack){ child->isBlack = true; free(node); if(node == tree->root){ tree->root = child; } return; }else{ //node will never be root, because child is black, and exactly one child exists //so node->parent will never be tree->nil RBNode* sibling = node == node->parent->left ? node->parent->right : node->parent->left; if(!sibling->isBlack){ node->parent->isBlack = false; sibling->isBlack = true; if(node == node->parent->left){ leftRotate(tree, node->parent); }else{ rightRotate(tree, node->parent); } }else{ if(node->parent->isBlack && sibling->left->isBlack && sibling->right->isBlack){ sibling->isBlack = false; RBDeleteNode(tree, node->parent); }else if(!node->parent->isBlack && sibling->left->isBlack && sibling->right->isBlack){ sibling->isBlack = false; node->parent->isBlack = true; }else if(node == node->parent->left && sibling->right->isBlack && !sibling->left->isBlack){ sibling->isBlack = false; sibling->left->isBlack = true; rightRotate(tree, sibling); }else if(node == node->parent->right && sibling->left->isBlack && !sibling->right->isBlack){ sibling->isBlack = false; sibling->right->isBlack = true; leftRotate(tree, sibling); }else{ sibling->isBlack = node->parent->isBlack; node->parent->isBlack = true; if(node == node->parent->left){ sibling->right->isBlack = true; leftRotate(tree, node->parent); }else{ sibling->left->isBlack = true; rightRotate(tree, node->parent); } } } } } free(node); }