Reputation:
I had an unordered Binary tree and I had to do a method that remove the subtree of root x. If the element x is present several times in the binary tree, the method remove only one of the subtree of root x (the first it finds). If the deletion was performed, returns true. If the element x is not present in the binary tree, returns false. So the method is:
public class BinaryTree
{
protected class Node
{
Integer element;
Node left;
Node right;
Node(int element)
{
this.element = element;
left = right = null;
}
Node(int element, Node left, Node right)
{
this.element = element;
this.left = left;
this.right = right;
}
protected Node root;
public BinaryTree()
{
root = null;
}
private class BoolNode
{
boolean ft;
Node nodo;
BoolNode(boolean ft, Node nodo)
{
this.ft = ft;
this.nodo = nodo;
}
}
public boolean removeSubtree(int x)
{
BoolNode ris = removeSubtree(x, root);
//root = ...;
return ris.ft;
}
private BoolNode removeSubtree(int x, Node node)
{
return null;
}
}
I do not know how to start, does anyone have any idea? Even pseudocode.. Thanks!
Upvotes: 3
Views: 9824
Reputation: 6610
Should go something like this....
if N is a parent,
removeNodes(N.left);
removeNodes(N.right);
remove(N);
repeat until you hit a leaf
private void removeNodes(Node base); //prepare for this when the teacher asks you why it's private
// - because you do not want to expose this functionality outside of the class;
// the only 'interface' exposed is the wrapper call removeSubtree(...) as the user shouldn't worry about the internal functionality.
removeSubtree() is a wrapper around the recursive removeNodes();
EDIT: ok so to clarify your mistery. Presume we have this tree
1 --- this is root
/ \
3 7
/ \ / \
(a) 5 4 3 2 //these branches don't matter right now
/ \
5 6
/ \ / \
5 4 3 2
Now, presume you call removeSubtree(5, root);
It will traverse the tree until it hits node (a) - the first 5 on the left. The way your current code is written you will do this: it will find the node with value X (5); then for all his left and right subchildren it will look for value 5.
Lets focus on this
1 --- this is root
/ \
3 7
\ / \
4 3 2
This is what you should get after calling removeSubtree(5, root); In other words, look at the subtree that is supposed to be deleted after finding the first node with value 5 and deleting it's children
5 -- we should delete all of these starting from here
/ \
5 6
/ \ / \
5 4 3 2
But your code will subsequently look for values 5 to delete in that subtree. That is why you need a general-purpose deleteSubtree() routine which will traverse the tree and delete everything it finds. Your removeSubtree(int, node) routine must rely on it or 'inline' it by implementing that mechanism itself.
Right now your code will only delete this
1 --- this is root
/ \
3 7
/ \ / \
(a) 5 4 3 2 //these branches don't matter right now
/ \
(b) 5 6
/ \ / \
(c) 5 4 3 2
In other words, it will land on node A (first 5), and instead of deleting everything below node (a), it will search for another value 5 below A, find (b) and try to delete it's subtree, matching only node (c).
The end result will be this - your code will delete only the three fives and leave you with this
1 --- this is root
/ \
3 7
/ \ / \
x 4 3 2
/ \
x 6
/ \ / \
x 4 3 2
Do you now realize why you cannot use the same function recursively? :) at least not in the way you want it right now. However, you can try this -
removeSubtree(node.left.value, node);
removeSubtree(node.right.value, node);
removeNode(node);
This will effectivelly find the right subtree - node (a), and then call itself to match it's children - nodes 5 and 6 (at depth of node (b)) and thus delete them. In any case, you cannot re-use value X in these calls like you used to do with
removeSubtree(x, node.left);
removeSubtree(x, node.right);
removeNode(node);
I hope that clarified something :) heh maybe i should teach this :D
Upvotes: 6