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();
Related
Been trying to solve this for a while now. I've been given a Node in a Disjoint Set.The Node's implementation is as a class where either it has a different parent node or is it's own
class Node {
Node parent;
int rank;
//...constructor and method declarations}
Now, I have to implement the Find method for this class with path compression, called the getParent() method. I wrote the following code:
Node getParent(){
while(parent != this)
{
parent = parent.getParent();
}
return parent;
I get infinite recursion with this code. I know it's problematic, but I do not know how to fix it. I tried using the this keyword, but it led to the same errors.
Please help. Also, an insight on how to write this code in an iterative manner would be a great plus.
Also, I would like to restructure the tree such that all intermediate nodes between the node on which the getParent() is called and the root have a common parent i.e. the root node.
The first part of your question is already answered by Stephen, and I think this is complete enough.
About the second part of your question, I assume you have all the nodes in a list. So you have List<Node> allNodes. The needed method to restructure the tree would be:
public void reStructureTree(List<Node> allNodes){
for(Node item: allNodes){
Node p = item.parent;
List<Node> branch = new ArrayList<>();
while (p.parent != p){
branch.add(p);
p = p.parent;
}
for(Node branchItem : branch){
branchItem.parent = p;
}
}
}
The order of this method in the worst case would be O(n^2) and I did not look for a better way, cause you didn't mention the importance of it.
Node getParent() {
while (parent != this) {
parent = parent.getParent();
}
return parent;
}
The problems:
You are mutating the parent field.
You should be testing if the parent's parent is itself ... not this.
Your code should probably be:
Node getParent() {
Node p = parent;
while(p.parent != p) {
p = p.parent;
}
return p;
}
Or recursively:
Node getParent() {
return (parent == this) ? this : parent.getParent();
}
(In this case, the iterative version is safer. You should not get "infinite" recursion, but there is still a risk that you may recurse too deep, with a pathologically deep data structure.)
UPDATE - apparently, it is your intention that getParent should (incrementally) collapse the parent chain of each Node it visit. In that case, the recursive solution would be:
Node getParentAndCollapse() {
if (parent == this) {
return this;
} else {
parent = parent.getParentAndCollapse();
return parent;
}
}
An iterative solution that collapses the entire chain requires two traversals of the chain:
Traverse the chain find the ultimate parent.
Traverse the chain again, updating all the parent fields to refer to the ultimate parent.
Return the ultimate parent.
Something like this
Node getParentAndCollapse() {
Node p = getParent(); // iterative version
Node n = this;
while (n.parent != p) {
Node np = n.parent;
n.parent = p;
n = np;
}
return p;
}
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.
This question is very abstract and thus very hard to describe or search for, thus why I am here. It's a very simple question however.
I have the following class:
class Node<T>
{
Comparable data;
Node<T> left, right;
public Node(Comparable data)
{
this.data = data;
}
}
What happens if I have:
/*
* Imagine this root looks like the following:
* 10 (root)
* / \
null null
*/
Node root;
// Imagine we are inside of the insert method and this
// is the current value that is going to be inserted.
int valueIAmTryingToInsert = 5;
// As we see from the tree above, "child" WILL be null.
Node child = (valueIAmTryingToInsert.compareTo(root.data) < 0 ? root.left : root.right);
if (child == null)
{
child = new Node(data);
return true;
}
// Recursive statement would happen here.
Notice that child is a pointer that points to either the left or the right child of root. BUT, what happens if I instantiate the Node that child is pointing to? After calling child = new Node(data);, does the tree currently look like:
10 (root)
/ \
5 null
If It doesn't look like that, explain why. Because my understanding is even though Node child is null, the pointer is still pointing to one of root's children. I am pretty sure this doesn't work, as my editor underlines child in the statement child = new Node(data); and claims The value new Node(data) assigned to 'child' is never used (even though it is being used).
You are never assigning it to the root node as its "left".
In plain English this is what your code does:
-Is the left (or right) of the root null?
-Yes
-Create a new node please.
But there's no association between this new Node and the root Node.
You might need something like this:
Node root;
Node child;
Integer valueIAmTryingToInsert = 5;
if(valueIAmTryingToInsert.compareTo(root.data) < 0){
if(root.left == null){
root.left = new Node(valueIAmTryingToInsert);
}
child = root.left;
}else{
if(root.right == null){
root.right = new Node(valueIAmTryingToInsert);
}
child = root.right;
}
return true;
EDIT:
This code is just an example, but if root.data is null you'll get a NullPointerException because of the comparision. That's something you might be aware and take care of.
EDIT 2:
I can see you're still confused and the main issue is that you have to keep in mind that null is not a reference to an object. It is a "mark" that indicates that the object has not been yet initialized. So when I say a = null; b = a is not like a and b are pointing to the same object (Because nullis not a valid object or reference), it means they both have not yet been initialized. They are separate independent variables. Then when I initialize one a = new MyClass() I'm asking for a memory reference for a, but b remains pointing to nowhere in memory.
See null as a way of telling "This object is pointing to nowhere".
If things were as you are thinking (If I initialize a then b should point there too); then every single null object in the program should point to where a is now pointing to.
You need to understand that child = new Node() will change what object your pointer points to, not any values of the object the pointer pointed to before and definitely not what object other pointers point to (like root.left).
root.left and child are NOT the same variable, even after calling child = root.left! They only point to the same object. So changing what one points to does not influence the other.
Basically, new Node() creates a new object somewhere in your memory. child = new Node() does the same thing, except afterwards it tells the variable child to point to that newly created object instead of whatever it pointed to before.
Hi I'm working on an assignment about hash table. Everything is fine except for the remove method.
Here's code:
public boolean remove(K key) throws HashTableException {
//
//IMPLEMENT THIS FUNCTION
//
if (key == null)
throw new HashTableException("Null keys not allowed in the hash table");
int index = getIndex(key);
HashTableNode<K,V> node = FindNode(key,index);
if (node == null) {
return false;
} else {
if (node.getNext() == null) {
node = null;
} else {
node = node.getNext();
}
return true;
}
}
It doesn't remove the key at all. Can anyone help me please? thank you!
node = null; does not "delete" the node, it just sets the value of the variable node in this method to null. It does nothing to the actual node that is in the hashtable somewhere.
And in the next "else" you then have node = node.getNext(); which, again, only change the node variable in this method. But since you return from the method without doing anything more with this variable, all this does is nothing since node is a local variable that only exists in this method.
You should read up on the concepts of local variables and references in java, which would probably lead to an understanding of why this is not working :)
node = node.getNext();
By this line, I think you are just traversing instead of re-writing the Next pointer
Maybe you should try node.getPrev().setNext = node.getNext();
if you can find the previous node and be able to set the next node.
Please make sure hashcode() and equals() are overridden correctly.
I'm writing some code that uses a Tree (a regular tree that can have an unlimited number of nodes, but no crossover, i.e. two parent nodes will not point the the same child node). Anyway, two things:
1) Are there any well-known algorithms for finding a sub-tree within a tree.
2) Are there any Java libraries (or any libraries for that matter) that already implement this algorithm? Even if there are none, can anyone recommend any good general purpose Java tree library?
I want to use these trees for holding data in a tree format, not for their searching capabilities.
To expand a bit: I'm using the tree as part of game to keep a history of what happens when a certain events happen. For example, an A can hit a B which can hit two A's which can hit another two A's etc.
That would look something like:
A
|
B
/
A
/ \
A A
/ \
A A
Of course there's more than just A and B. What I want to do is (for an achievement system) is be able to tell when, say an A has hit two A's:
A
/ \
A A
I want to be able to easily know if the first tree contains that subtree. And I don't want to have to write all the code for doing so if I don't have to :)
Looks like a straightforward algorithm: Find the root of the search tree in the game tree and check whether the children of the search tree are a subset of the children in the game tree.
From your explanations, I'm not sure whether the search tree
A
/ \
A A
should match this tree:
A
/|\
A C A
(i.e. if non-matching children are supposed to be ignored.)
Anyway, here's the code I just toyed around with. It's a fully running example and comes with a main method and a simple Node class. Feel free to play with it:
import java.util.Vector;
public class PartialTreeMatch {
public static void main(String[] args) {
Node testTree = createTestTree();
Node searchTree = createSearchTree();
System.out.println(testTree);
System.out.println(searchTree);
partialMatch(testTree, searchTree);
}
private static boolean partialMatch(Node tree, Node searchTree) {
Node subTree = findSubTreeInTree(tree, searchTree);
if (subTree != null) {
System.out.println("Found: " + subTree);
return true;
}
return false;
}
private static Node findSubTreeInTree(Node tree, Node node) {
if (tree.value == node.value) {
if (matchChildren(tree, node)) {
return tree;
}
}
Node result = null;
for (Node child : tree.children) {
result = findSubTreeInTree(child, node);
if (result != null) {
if (matchChildren(tree, result)) {
return result;
}
}
}
return result;
}
private static boolean matchChildren(Node tree, Node searchTree) {
if (tree.value != searchTree.value) {
return false;
}
if (tree.children.size() < searchTree.children.size()) {
return false;
}
boolean result = true;
int treeChildrenIndex = 0;
for (int searchChildrenIndex = 0;
searchChildrenIndex < searchTree.children.size();
searchChildrenIndex++) {
// Skip non-matching children in the tree.
while (treeChildrenIndex < tree.children.size()
&& !(result = matchChildren(tree.children.get(treeChildrenIndex),
searchTree.children.get(searchChildrenIndex)))) {
treeChildrenIndex++;
}
if (!result) {
return result;
}
}
return result;
}
private static Node createTestTree() {
Node subTree1 = new Node('A');
subTree1.children.add(new Node('A'));
subTree1.children.add(new Node('A'));
Node subTree2 = new Node('A');
subTree2.children.add(new Node('A'));
subTree2.children.add(new Node('C'));
subTree2.children.add(subTree1);
Node subTree3 = new Node('B');
subTree3.children.add(subTree2);
Node root = new Node('A');
root.children.add(subTree3);
return root;
}
private static Node createSearchTree() {
Node root = new Node('A');
root.children.add(new Node('A'));
root.children.add(new Node('A'));
return root;
}
}
class Node {
char value;
Vector<Node> children;
public Node(char val) {
value = val;
children = new Vector<Node>();
}
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append('(');
sb.append(value);
for (Node child : children) {
sb.append(' ');
sb.append(child.toString());
}
sb.append(')');
return sb.toString();
}
}
Are you looking for any particular constraints on a subtree? If not, a simple traversal should suffice for identifying subtrees (basically treat each node as the root of a subtree).
I believe you'll find that the API you'll want for a tree varies a great deal by your particular application -- so much that generic implementations are not very useful. Perhaps if you could tell us what kind of application the tree will be used for, we could provide particulars.
Also, if you're just using a tree for data storage, you might want to ask yourself why you need a tree. That answer should also answer the question in my previous paragraph.
I wonder if there's an extension of the Knuth algorithm that would be more efficient than a naive traversal...
If there is one big, static, tree and you will be searching for many subtrees in the same big tree, you might want to annotate each node with the set of hashes of all of its subtrees to a given depth depending on how much storage you're willing to expend on that functionality. Then build a map from hash values to the set of nodes that are roots of a subtree with that hash value. Then just check each one of those, presumably much cheaper than a traversal, for the hash of the root of the query tree to that same depth.