This question already has answers here:
Deleting an object in java?
(7 answers)
Closed 6 years ago.
The task is commonly done during recursive post order traversal, and there are few examples online. One of them is here, but I wonder if it's correct because it seems that the _deleteTree() method only does a BFS and does no operation to nodes, and the deletion is done by simply set the root of the tree to null. It will no doubt return an empty tree. But is it the correct way to remove references to all the tree nodes?
Also, for iterative post order traversal, say, like below
public TreeNode postorderTraversal(TreeNode root) {
if(root==null) return null;
Stack<TreeNode> stack1=new Stack<>();
Stack<TreeNode> stack2=new Stack<>();
TreeNode cur=root;
stack1.push(cur);
while(!stack1.isEmpty()){
cur=stack1.pop();
if(cur!=null){
stack2.push(cur);
}
if(cur.left!=null){
stack1.push(cur.left);
}
if(cur.right!=null){
stack1.push(cur.right);
}
}
while(!stack2.isEmpty()){
//elements poped will be in post order sequence
}
return root;
}
How to destroy a binary tree iteratively? Can someone give a sample code (java)?Thanks!
There's a better solution, which uses the tree nodes themselves to store the queue. Something like this:
static void clear(Node root) {
while (root != null) {
Node left = root.left;
if (left == null) {
Node right = root.right;
root.right = null;
root = right;
} else {
// Rotate the left child up.
root.left = left.right;
left.right = root;
root = left;
}
}
}
Usually when you assign a node to null you technically get rid of all data. As with a linked list when you break its connection by setting its "next" per say to null you delete the list and java garbage collector takes care of the rest. So in the Java code you linked they are doing the same thing once the root is determined to have no children.
Related
I will receive something like:
public int count (Tree myTree){
}
I already have the Tree definition, getLeft(), getRight() methods.
I have seen some examples, but always they receive a node as parameter, I need to receive the Tree as parameter.
Could anyone please help me? I'm new on this topic.
Thanks
Here Tree is the node class itself, meaning the name is given differently.
So myTree parameter is a node itself of the given Binary Tree, here pointing to the root in the given function.
Now Tree and the node class itself in the picture below, where the right child and left child and the data of the current node are stored.
So to find out the number of nodes of a given tree,
You have to first check if the given myTree is null or not, meaning if the given myTree doesn't have any Root node only.
Then you have to return 0.
int count(Tree myTree)
{
if (myTree == null)
return 0;
int res = 0;
if (myTree.left != null && myTree.right != null)
res++;
res += (count(myTree.left) + count(myTree.right));
return res;
}
Hope it helps :D
A tree in fact is defined by its root node, but let's just say you implemented the Tree in your own way :p and that you have a function to get the root getRoot(), you can use recursion as it follows to count the number of nodes in your tree (we assume that for a node you can access the children with getLeft() and getRight(), you have to implement a function to construct a tree from a node constructTree(Node root)):
public int count (Tree myTree){
Node root = myTree.getRoot();
return root != null ?
1 + count(constructTree(root.getLeft()) +
count(contructTree(root.getRight()))
: 0;
}
Here in count (Tree myTree){ }
Tree is the Node class only and you'll receive root node as a parameter which here is myTree
Because without root node it is impossible to access tree.
And in java Collections there is no such thing as Tree. So rest assured you are on right track.
Assuming Tree == Node as you have described your problem, then one approach is to use recursion:
public static int count(Tree tree) {
Tree left = tree.getLeft();
Tree right = tree.getRight();
return 1 +
(left != null ? count(left) : 0) +
(right != null ? count(right) : 0);
}
So I know for a binary tree the general way to preorder traverse it is like this
void displayPreOrder(TreeNode node)
{
if(node != null)
{
displayPreorder(node.left);
displayPreorder(node.right);
System.out.println(node.value);
}
}
But I'm having trouble trying to wrap my head around a preorder traversal of a quadtree. I've tried to find some resources, but left empty handed. Any hint?
The code you posted is for a postorder traversal of a binary tree. For a quadtree, you just need to visit all children instead of just left and right.
For simplicity, I'll assume that TreeNode defines a method children() that returns an iterator or a List of the node's children in some well-defined order. If that's not available, just iterate through the children using whatever mechanism is available.
void displayPreOrder(TreeNode node)
{
if(node != null)
{
// visit the root first for pre-order
System.out.println(node.value);
for (TreeNode child : node.children()) {
displayPreorder(child)
}
}
}
(P.S. This works for binary trees as well, given the right iteration mechanism.)
I read a postorder traversal application to delete a binary tree and a code which is written in c++.
I am wondering how to write this code for java. I think we have to set the node as null in postorder way.
void delete(Node root)
{
if (root!=null){
delete(root.left);
delete(root.right);
}
root=null;
}
root = null
C++ isn't garbage collected, but Java is. In Java, once an object no longer has any references to it, it will be automatically removed from memory. All of the referenced objects of the garbage collected object will also be removed if they have no other references to them. That bit addresses your question: if the nodes under root don't have any external references, they will be automatically removed after root.
Trivially root = null;. However there is a difference with C++ as Java cannot change a passed variable:
delete(root);
will never set root to something else. This was a design principle to make Java more qualitative in software engineering sense (less error prone) than C++ (Node*&).
You need to use return values, as there are no output values.
A modified example:
Node deleteSubtree(Node tree, Object value) {
if (tree == null) {
return null;
}
if (value.equals(tree.value)) {
return null; // Deleting a subtree
}
tree.left = delete(tree.left, value);
tree.right = delete(tree.right, value);
return root;
}
NOde root = ...
root = delete(root, "war");
This would delete the subtree rooted at "war".
You simply need to unlink the left and right nodes from the root:
void delete(Node root)
{
if (root!=null){
delete(root.left);
root.left = null;
delete(root.right);
root.right = null;
}
}
Setting root to null is useless, because it is a local variable that will be unlinked when the method returns anyway. Also it does not affect the value in the calling method, so it has no effect at all.
Just do root = null and the garbage collector will delete the whole tree during the garbage collection as no reference to the tree root is available in the program.
public class BinaryTree {
Node root;
public BinaryTree() {
root = null;
}
void deleteTree(Node node){
if(node==null)
return;
deleteTree(node.left);
deleteTree(node.right);
System.out.println("The deleted node is " + node.key);
node = null;
}
void deleteTreeRef()
{
deleteTree(root);
root=null;
}
}
And client will call like following:
tree1.deleteTreeRef();
I am hopelessly lost when it comes to recursive functions. I am required to create a recursive function to traverse a binary tree and insert a new node in between specific values. Would i need to recopy my traverse function and modify it in every other function that i use it in? Would someone please evaluate the traverse function?
I think my traversing code is alright.
Node traverse (Node currentNode){
if (!currentNode.left.equals(null)){
traverse (currentNode.left);
return currentNode.left;
}
if (!currentNode.right.equals(null)){
traverse (currentNode.right);
return currentNode.right;
}
return currentNode;
}
When it comes to binary trees, there are several different types of traversals that can be done recursively. They're written in the order they're referenced then visited (L=Left child, V = visit that node, R = right child).
In-order traversal (LVR)
Reverse order traversal (RVL)
Preorder traversal (VLR)
Postorder traversal (LRV)
Your code appears to be performing the postorder traversal method, but you're getting a few things mixed up. First, the node is what you want to traverse; the data is what you want to visit. Second, you have no reason to return the node itself, in the way that this is implemented. Your code doesn't allow for a condition to say, 'I'm looking for this particular data, do you have it Mr. Node#0xdeadbeef?', which would be found with some sort of extra search parameter.
An academic BST traversal only prints the nodes itself. If you wanted to add a search functionality, it's only one more parameter, as well as an additional check for the right node.
Here's a snippet:
// Academic
public void traverse (Node root){ // Each child of a tree is a root of its subtree.
if (root.left != null){
traverse (root.left);
}
System.out.println(root.data);
if (root.right != null){
traverse (root.right);
}
}
// Search with a valid node returned, assuming int
public Node traverse (Node root, int data){ // What data are you looking for again?
if(root.data == data) {
return root;
}
if (root.left != null && data < root.data) {
return traverse (root.left, data);
}
if (root.right != null && data > root.data) {
return traverse (root.right, data);
}
return null;
}
It seems like you are traversing in the preorder methodology, but i am a little skeptical as to what exactly you wish to accomplish without actually comparing your current node with some base value that defines u have reached ur destination. I would suggest drawing out a simple tree and visualizing the steps. Then try to put that into code.
A recursive function returns the value of itself with a modified parameter, or a termination (exit) condition. eg, Factorial:
int factorial( int param ) {
if ( param > 1 ) {
return param * factorial( param -1 );
} else {
return 1;
}
}
In your code, you call a 'traverse' but then do nothing with the result...
When your recursive function ends, your final return will be first left child if it exists, else the first right child if it exists, else the root node.
Please give more detail as to why you need to traverse the tree (also, not sure what you meant by "copy the function and modify it in every other function", the whole idea of a function is to code-once-call-many)
Okay. I have a binary tree, and this is what I want to do with it:
For each node in original tree:
If it's not a leaf, replace it with a leaf node.
Do a calculation on the original tree updated with the removed branch.
Revert the node back to how it was (so now the tree is the same as at the beginning).
The problem is this: I am traversing the tree using a stack. If I change the stack.pop() node to a leaf, this does NOT remove any branches in the original tree. It's the same reasoning behind why you can do:
int x=1
int y=x
y++
And x still equals 1. There's a technical term for this but I forgot it.
So how can I edit the nodes in an original tree and still traverse it?
This is basically what I'm doing to traverse the tree right now:
public void iterativePreorder(Node root) {
Stack nodes = new Stack();
nodes.push(root);
Node currentNode;
while (!nodes.isEmpty()) {
currentNode = nodes.pop();
Node right = currentNode.right();
if (right != null) {
nodes.push(right);
}
Node left = currentNode.left();
if (left != null) {
nodes.push(left);
}
//This is where you do operations on the currentNode
}
}
From what I can tell from your question, for every Node you want to calculate something about the tree as if that node was a leaf.
To do this there is no reason to actually make that node a leaf and then reattach it. Instead, your logic can simply remember which node to treat as a leaf for each computation.
Traverse the tree, and for each Node, let's call it outerCurrentNode, once again traverse the tree doing your calculation - but now for each Node, let's call it innerCurrentNode, test to see if outerCurrentNode == innerCurrentNode. If the test returns true, treat that innerCurrentNode as if it's a leaf, ignoring its children.
EDIT: Here's a mock up of what I'm suggesting (untested):
//entry point - called from directing code
public void iterativePreorder(Node root) {
iterativePreorderKernel(root, root);
}
//recursive method - keeps track of root in addition to current Node
private void iterativePreorderKernel(Node root, Node current) {
if (current.left() != null) {
iterativePreorderKernel(root, current.left());
}
if (current.right() != null) {
iterativePreorderKernel(root, current.right());
}
//for each Node in the tree, do calculations on the entire tree, pretending
//the current Node is a leaf
doCalculation(root, current);
}
//calculation method (also recursive) - takes a current Node, plus
//the Node to treat as a leaf
public void doCalculation(Node innerCurrent, Node pretendLeaf) {
//do calculation with inner current node
if (innerCurrent != pretendLeaf) {
if (innerCurrent.left() != null) {
doCalculation(innerCurrent.left(), pretendLeaf);
}
if (innerCurrent.right() != null) {
doCalculation(innerCurrent.right(), pretendLeaf);
}
}
}
I'm using recursion instead of a Stack, but either will work. iterativePreorder() does a traversal, calling doCalculation() for each Node, passing it in along with the root (to keep track of the entire tree). That method then does its own traversal, doing your calculation, but stopping short when it reaches the specially marked Node.