问题
Ok so I thought it was fixed, but I'm getting totally inconsistent results. I rewrote it kind of from scratch to start fresh and here are my results. I get no errors, no crashing, it just doesn't remove them. It just totally messes up the tree and gives me a ton more leaves, and mixes everything up. Not sure where else to go
template <class T>
void BST<T>::remove(struct Node<T>*& root, const T& x)
{
Node<T>* ptr = root;
bool found = false;
Node<T>* parent;
while (ptr != NULL && !found)
{
if (x < ptr->data)
{
parent = ptr;
ptr = ptr->left;
}
else if (x > ptr->data)
{
parent = ptr;
ptr = ptr->right;
}
else
found = true;
}
if (found == false)
return;
else
{
if(ptr->left != NULL && ptr->right != NULL)
{
Node<T>* inOrderPtr = ptr->left;
parent = ptr;
while (inOrderPtr->right != NULL)
{
parent = inOrderPtr;
inOrderPtr = inOrderPtr->right;
}
ptr->data = inOrderPtr->data;
ptr = inOrderPtr;
}
Node<T>* subPtr = ptr->left;
if (subPtr == NULL)
subPtr = ptr->right;
else if (parent->left == ptr)
parent->left = subPtr;
else
parent->right = subPtr;
delete ptr;
}
回答1:
Are each T found in the tree unique? It looks like they are from your code...
It looks like this should work:
In the else case deleting the root node:
Node<T> *tmp_r = root->left;
Node<T> *parent = root;
while (tmp_r->right != NULL)
{
parent = tmp_r;
tmp_r = tmp_r->right;
}
Node<T> *tmp_l = tmp_r;
while (tmp_l->left != NULL)
tmp_l = tmp_l->left;
tmp_l->left = root->left;
tmp_r->right = root->right;
parent->right = NULL;
parent = root;
root = tmp_r;
delete parent;
回答2:
What actually was happening is that might searches were reversed so it would actually just keep going right but the data wasn't really matching correctly and so it would hit a wall it seems.
if (root->data < x)
remove(root->left, x);
else
remove(root->right, x);
should have been
if(x < root->data)
remove(root->left, x);
else
remove(root->right, x);
回答3:
You shouldn't be calling remove()
recursively in the third case (where your "not sure if this is right" comment is). In the case where the the node to remove has two children, what you want to do is find the right-most child of the left child (as you are doing; the resulting node is stored in parent
). This node has no right child - make it so that its right child is the right child of the node to be deleted. Then just change the root
variable to be its left child; no need to change the data
member in any nodes or to call remove
recursively.
In pictures:
Before: r <- root points here / \ / \ a b / \ / \ x c y y / \ x d / x After: a <-- root points here / \ x c / \ x d / \ x b / \ y y
来源:https://stackoverflow.com/questions/245838/binary-search-tree-deletion-inorder-pred-method-c