Delete Binary Tree - Suggestions on Design - java

I have written a code for deleting all elements of tree.
Need suggestions for following:
In reverseTreeStack method, Can I design without using stack method parameter?
Can I design the entire code in 1 method with better design?
UPDATE : Changed return type of reverseTreeStack to void.Removed additional variable for stack.
public class DeleteTree {
public static void deleteTree(BinaryTreeNode root)
{
Stack stack = new Stack();
reverseTreeStack(stack, root);
while (!stack.isEmpty())
{
BinaryTreeNode node = (BinaryTreeNode)stack.pop();
System.out.println("---------Deleting----------->" + node.getData());
node = null;
}
}
public static void reverseTreeStack(Stack stack,BinaryTreeNode root)
{
if (root != null)
{
stack.push(root);
reverseTreeStack(stack,root.getLeft());
reverseTreeStack(stack, root.getRight());
}
}
}

Why do you need to do this? If I recall correctly, the JVM can free resources once there are no available references to the resource, so just setting your root node to be null should free the whole tree.

I think, James is right, but if you want to practice the tree traversal, or if you want to implement this in a language where you need to free memory manually, then use recursion:
void deleteTree(TreeNode node)
{
if(node==null)return;
deleteTree(node.getLeft());
deleteTree(node.getRight());
System.out.printline("Deleting: "+node.getData())
node = null;
}
Also take a look at Postorder Traversal (thats the only one, that works for deleting)

1) I think you can kill the return value and make it a void method as you are directly manipulating the stack. So just do
Stack stack = new Stack();
reverseTreeStack(stack, root);
// Now just use stack
2) Don't condense things into one method. Breaking things out into more methods will make your code easier to navigate and understand. The less each function is responsible for, the more sense it will make to someone reading it.

Well your reverseTreeStack method can potentially give you a StackOverflowError if your tree is too large, so using a loop instead of recursion there might be a better choice (unless you know for a fact that your trees will never be that large).
Also, why are you "deleting" every node? (node = null actually just removes the reference you have just in that method...) Generally just forgetting the root (root = null) will delete your whole tree if you're structuring it in the classic way of Node(parent, leftChild, rightChild) and not storing pointers to nodes anywhere else.

Related

To delete an entire linked list in java which I have created

I want to delete an entire list which I have created in java(note: I am not using internal list in java.util). I have assigned head to null but my question is will the java garbage collector handle the list which has no head or should I delete every node(I mean setting every node to null) which will be handled by java garbage collector? Following is my code, please let me know which one is ok although both works but I would still like to know. Thanks in advance.
//first code
public void deleteList()
{
Node n = head;
Node n1;
head = null;
System.out.println("Deleting list");
while(n != null)
{
n1 = n;
n = n.next;
n1 = null;
}
n1 = n;
n1 = null;
System.out.println("List deleted");
}
//second code
public void deleteList()
{
head = null;
}
It depends on your implementation. If your Node class is internal only (so you don't ever return a Node where it might be saved) and you don't hold any in statics, then there should be no path to any node from a garbage collection root and GC will get rid of them.
So it's probably right, unless your implementation is doing something unusual. (I'm also assuming you don't have a tail variable or anything else that references an internal Node, because those would also need to be set to null).
The Garbage Collector will destroy an object only when the particular object doesn't have any linked internal dependency to other nodes. In other words, whenever the objects are not referenced anymore, they are destroyed and their memory is reclaimed.
your first code is right, when you have internal dependency with other nodes i.e, tail node, for example.
your second is right, when you doesn't have any dependency with other node.

Stack not pushing items into the collection

My implementation of the collection is as follows:
private void init(Node<K, E> root) {
Node<K,E> node = root;
while (node != null) {
stack.push(node);
node = node.getLeft();
}
}
However when it gets invoked and used, it seems that there is nothing in the Stack. I've tried debugging exhaustively without any avail, any suggestions as to what might be going wrong in the way I implemented the above components?
You've made your Stacks immutable. When you call the push() method, it doesn't actually push the node on to the stack, it returns a new immutable Stack with that element pushed on to it. When calling all modifying methods such as push and pop, prepend stack = on the line to assign the newly returned stack back to stack.
E.g. replace
stack.push(node);
with
stack = stack.push(node);

How to optimize my Trie implementation so that I don't get OutOfMemoryError

I'm implementing text predictions using a very simple Trie implementation, which is a slightly modified version of this code
It performs better than I initially expected, but I'm receiving an OutOfMemoryError frequently. Any ideas how can solve this problem by either:
increasing the memory designated to my app
optimizing the implementation to use less memory
or any other suggestions?
I've seen recommendations that the memory limitation problems could be avoided by using a native implementation of a part of the code, but I would prefer to stay in Java, if possible.
You could try turning on largeHeap in your manifest to see if it helps:
http://developer.android.com/guide/topics/manifest/application-element.html#largeHeap
By doing this.next = new Node[R]; the implementation allocates an array with 26 pointers to nodes on level 1, then 26^26 pointers to nodes on level 2, then 26^26^26 on level 3 and so on. That could be one reason you run out of memory.
You can try and change the implementation so that every Node has a HashMap of nodes with a small initial capacity, say 5. The HashMap will grow only when there's a real need - which will save some memory.
Another problem in that code is with the delete:
// delete a node
public void delete(Node node) {
for(int i = 0; i < R; i++) {
if(node.next != null) {
delete(node.next[i]);
}
}
node = null; // <-- this is not doing anything!
}
The reason it's not doing anything is that the reference to the node is passed by value in Java - so the real reference remains intact. What you should do instead is:
// delete a node
public void delete(Node node) {
for(int i = 0; i < R; i++) {
if(node.next != null) {
delete(node.next[i]);
node.next[i] = null; // <-- here you nullify the actual array item
} // which makes the object a good candidate for
// the next time GC will run
}
}
So it could also be a memory leak - in case you counted on delete to free space.

Creating a Deque Class methods

I need to write my own Deque class and must used a doublylinked list implementation to store data. the problem is writing the method pushfromLeft(Thing thing) which will insert into the left side of the deque. Below is what I have thus far but does not seem to work.
public void pushLeft(Thing thing) {
Node beg = new Node();
Node end = new Node();
Node T = new Node();
if(isEmpty())
{
beg = first;
end = last;
beg = end;
T = beg.thing;
N++;
}
else
{
beg = beg.next;
end = end.next;
T = beg.previous;
N++;
}
Little you do in that method has any effect outside, except changing N and item. Presumably you should be modifying first. It would help if you provide the fields of your class, and what they mean, for context. For instance, it's not clear what item is.
You should also either come up with different conventions for naming member and local variables, or consistently use this., or both.
Might I make a suggestion that may clear a lot of this up for you. it's not what you asked for, but it may be what you need.
Use OO design, this means not operating on something but asking something to operate on itself. What this means is that Node should be more intelligent--currently you are acting on node.
Since Node is doubly linked, it can be pretty smart! It can have methods like:
newNode.insertBefore(currentNode)
newNode.insertAfter(currentNode)
currentNode.remove()
Once you have those, the rest of your code should clean up a bit. They should be trivial to implement given a doubly linked list.
void insertBefore(node existing) {
// first set my stuff up
previous = existing.previous;
next = existing;
// then point other stuff at me
previous.next = this;
existing.previous = this;
}
I think--that's just off the top of my head.
The other question is how do you handle your "Endpoints". Your first and last pointers have to be instances of Node for this to work, but if they are notice that the whole "If" factors out of your original code! Sweet!
Just ALWAYS have a first and last object that start out pointing to each other (and never take on values). When you do your first add, do first.insertAfter() or last.insertBefore() and you are done.
Another possibility, by the way, is to make the list circular--there is no reason that First and Last couldn't be the same "Special" unassigned node, you could still traverse it's Next (which will give you the first real item in the list) and Previous (giving you the last item in your list).
When iterating the entire list, if .value == null, you know you've made it to the other end which makes node.next() and previous() fascinatingly easy to implement (You don't really even need to implement .next, but see below.
/** returns null if there are no more items in the list */
Node next() {
return next;
}
Try it, it will simplify your code a LOT. Most people really don't get how useful actual OO code is.
Also, make all your variables private, it's a good habit to get into. In this case when you are having nodes operate on each other, they can still access each other's private members (not as dirty as it sounds) so you can still have the insertBefore as I wrote it AND you don't have to have getters and setters or public variables. Best of both worlds.
Also notice how your original class that "Operated" on node all but disappears--in fact, it can go away completely. If you needed some specific methods like find(item) or insertSorted(item) there is no reason you couldn't add them to node itself. This may be hard to see until after you implemented it though.
Funny how if you actually code well, most of the complaints people have about Java just don't come up.
Have you looked at the LinkedList source code as a reference?
You definitly don't need to create more than one Node inside adding method. If you want to read from left AND from right later, each Node must remember previous and next element. Then when adding, you just need to re-locate these links, like this:
public void pushLeft(Thing thing) {
Node newNode = new Node();
newNode.setValue(thing); //or just newNode.value = thing;
if(this.isEmpty())
{
this.first = this.last = newNode;
this.n=1;
}
else
{
this.first.previous = newNode;
newNode.next = this.first;
this.first = newNode;
this.n++;
}
}
It vould be wise to create a constuctor for Node class which shoul automaticaly set the value, then you can just wite:
Node newNode = new Node(thing);

How to collect the result of a recursive method

I iterate through a tree structure to collect the paths of the leaf nodes. Which way do you prefer to collect the result of the operation:
a) merge the results of the children and return this
private Collection<String> extractPaths(final Element element, final IPath parentPath) {
final IPath path = parentPath.append(element.getLabel());
final Collection<Element> children = getElementChildren(element);
if (children.isEmpty())
return Collections.singletonList(path.toString());
final Set<String> result = new TreeSet<String>();
for (final Element child : children)
result.addAll(extractPaths(child, path));
return result;
}
b) provide the result collection as a parameter and add new elements in each recursion step
private void extractPaths(final Element element, final IPath parentPath, final Set<String> result) {
final IPath path = parentPath.append(element.getLabel());
final Collection<Element> children = getElementChildren(element);
if (children.isEmpty())
result.add(path.toString());
for (final Element child : children)
extractPaths(child, path, result);
}
Both can be used without any problems. Though, former solution is more clean since it doesn't change input parameters. No side effects is in the nature of functional programming.
I assume the latter is meant to call extractPaths(child, path, result)?
The latter form will be more efficient, as it doesn't need to copy items at every level of recursion. As Boris says, it's less functionally clean - but Java doesn't really provide immutable collections with appropriate methods to create new collections based on them efficiently.
In terms of making it pleasant to call, you could provide a wrapper in the style of the first option which just creates a new set and calls the second option. That's probably what I'd do:
private Collection<String> extractPaths(Element element, IPath parentPath) {
Set<String> ret = new HashSet<String>();
extractPaths(element, parentPath, ret);
return ret;
}
Another alternative is to change the third parameter from a Set<String> to some sort of "collector" interface: you tell it that you've found a result, without specifying what to do with it. Indeed, the collector could return a new collector to use from then on - leaving it up to the implementation to decide whether to make a functionally-clean "create a new set" version, or hide side-effects in the collector which would just return itself again for reuse.
To provide the most convenient and flexible interface to your clients, write it as a class that implements Iterator<E>.
This means that the client can loop through the items found during the recursion, but they don't have to implement their "for each" code as a callback (Java doesn't have a pretty way to do that), and they can even "pause" the operation and continue it later, outside of the scope in which they began it (or abandon it at any point).
It's the trickiest to implement though. If the data structure you're traversing is a tree-like structure with parent pointers in each node then you need no other data than the current node. To get to the next node, look for a first child. If there is one, that's the next node. Otherwise try the next sibling. If there isn't one, get the parent and try to get its next sibling, and so on until you hit a null in which case there are no more items.
As a quick and dirty example, here's a treenode-like class, breaking all the rules about encapsulation to save some space here:
class SimpleNode
{
String name;
public SimpleNode parent, firstChild, nextSibling;
public SimpleNode(String n) { name = n; }
public void add(SimpleNode c)
{
c.parent = this;
c.nextSibling = firstChild;
firstChild = c;
}
public String getIndent()
{
StringBuffer i = new StringBuffer();
for (SimpleNode n = this; n != null; n = n.parent)
i.append(" ");
return i.toString();
}
}
Now let's create a tree from it:
SimpleNode root = new SimpleNode("root");
SimpleNode fruit = new SimpleNode("fruit");
root.add(fruit);
fruit.add(new SimpleNode("pear"));
fruit.add(new SimpleNode("banana"));
fruit.add(new SimpleNode("apple"));
SimpleNode companies = new SimpleNode("companies");
root.add(companies);
companies.add(new SimpleNode("apple"));
companies.add(new SimpleNode("sun"));
companies.add(new SimpleNode("microsoft"));
SimpleNode colours = new SimpleNode("colours");
root.add(colours);
colours.add(new SimpleNode("orange"));
colours.add(new SimpleNode("red"));
colours.add(new SimpleNode("blue"));
Now, to spell this out for anyone new to this idea, what we want to be able to do is this:
for (final SimpleNode n : new SimpleNodeIterator(root))
System.out.println(n.getIndent() + "- " + n.name);
And get this (I've made the above code generate something that looks like a hierarchical bullet list in SO):
root
colours
blue
red
orange
companies
microsoft
sun
apple
fruit
apple
banana
pear
To do this, we have to map some standard operations onto our SimpleNode class:
class SimpleNodeIterator extends TreeIterator<SimpleNode>
{
public SimpleNodeIterator(SimpleNode root)
{ super(root); }
protected SimpleNode getFirstChild(SimpleNode of)
{ return of.firstChild; }
protected SimpleNode getNextSibling(SimpleNode of)
{ return of.nextSibling; }
protected SimpleNode getParent(SimpleNode of)
{ return of.parent; }
}
And finally, at the bottom of our design, TreeIterator<TNode> is a very reusable abstract base class that does the rest, now we've told it how to navigate our node class:
abstract class TreeIterator<TNode> implements Iterator<TNode>,
Iterable<TNode>
{
private TNode _next;
protected TreeIterator(TNode root)
{ _next = root; }
public Iterator<TNode> iterator()
{ return this; }
public void remove()
{ throw new UnsupportedOperationException(); }
public boolean hasNext()
{ return (_next != null); }
public TNode next()
{
if (_next == null)
throw new NoSuchElementException();
TNode current = _next;
_next = getFirstChild(current);
for (TNode ancestor = current;
(ancestor != null) && (_next == null);
ancestor = getParent(ancestor))
{
_next = getNextSibling(ancestor);
}
return current;
}
protected abstract TNode getFirstChild(TNode of);
protected abstract TNode getNextSibling(TNode of);
protected abstract TNode getParent(TNode of);
}
(It's mildly naughty in that it implements Iterator<E> and Iterable<E> on the same object. This just means that you have to new up a fresh object in order to iterate a second time; don't try to reuse the same object).
This means that if your hierarchical structure consists of nodes for which you can define those three simple navigational operations, then all you have to do is derive your own equivalent of SimpleNodeIterator. This makes it very easy to enable this capability on any tree implementation.
If what you're iterating doesn't have a way to get the parent, you need to keep a stack during the iteration. Each time you descend a level, you push the state for the current level onto the stack. When you finish iterating at the current level, you pop the last state off the stack and continue with it. When the stack is empty, you're done. This means you have some intermediate storage, but its maximum size is proportional to the depth of the recursion rather than the number of items, so assuming the data is roughly balanced then it should be a lot more storage-efficient than copying all the items to a list before you return it.
The final solution I found after some refactoring is to implement variant b) but to pass a Visitor instead of the result collection:
private void traverse(final Element element, final Visitor... visitors) {
for (final Visitor visitor : visitors)
// push e.g. the parent path to the stack
visitor.push(visitor.visit(element));
for (final Element child: getElementChildren(element))
traverse(child, visitors);
for (final Visitor visitor : visitors)
visitor.pop();
}
The Visitor provides also a stack to carry the information about the parent path. This solution allows me to separate the traversal logic from the collection logic, without the need of the more complex TreeIterator implementation.
private class CollectPathsVisitor extends ElementVisitor {
public final Set<String> paths = new TreeSet<String>();
public Object visit(Element element) {
final IPath parentPath = (IPath) peek();
final IPath path = parentPath.append(element.getLabel());
if (!hasChildren(element))
paths.add(path);
return path;
}
}
I usually prefer to return the result, since i think
$result = extractPaths($arg,$arg2);
is more clear than
extractPaths($arg,$arg2,$result);
but it's entirely based on taste.
I would choose option b, since it would create fewer objects and thereby be more efficient. Solution a feels more like the way you would do it in a functional language, but that relies on assumptions that don't hold in Java.
If you pass in the object to be built, if you had an exception that you caught in a place where you had a reference to that object, then you would at least have the data you built up until the exception was thrown.
I personally pass in Builders as arguments when multiple methods will be "building" on it, including recursion. This way you only have a single object being built, and miss out lots of Set, Map or List copying.
in this specific case I prefer the latter solution since:
it avoids creating throw-away collections
your algorithm implemented in this way cannot get any gain from being "functional"
imho there is no real benefit of being functional without a really good reason f (e.g. using threads).
pass a collection as parameter for this method
Later will create less objects in memory (as already said) but also manages each tree path only once: when extracted and stored in the Set result it is not 'addedAll' to any other set again and again and again.

Categories

Resources