Iterate over all nodes in a recursively defined tree - java

I am trying to make a node class that I will eventually be able to use for a minimax search, however I am having trouble iterating over all of the nodes in my tree (in this case for a simple to string function).
Here is the definition of the recursive to string method.
public String toString(){
if(!this.isLeaf()){
String text = "";
Iterator<Node<T>> iter = children.iterator();
while(iter.hasNext()){
Node child = iter.next();
text = "/" + child.toString();
}
return text;
}else{
return cargo.toString() ;
}
}
After reading other answers I tried using the Iterator interface as seen in the code above but it still didn't work. (I'm also open to non-recursive methods of doing this)

Did you mean +=?
text += "/" + child.toString();
^

I assume that you intended to concatenate the child values separated by a '/' as per tom's answer.
If you intend to build up a string, it is more efficient to use a StringBuffer, because otherwise each time around the loop a new String has to be allocated to take the new value, whereas a StringBuffer builds up in a buffer.
StringBuffer text = new StringBuffer();
for (Node<T> child : children) {
text.append('/');
text.append(child.toString());
}
return text.toString;
I've used a for-each style loop but the 'while' loop you used would still work as well.

Related

Fetch value from a set object in java

I'm iterating a set object to find a particular value. Is there any short way to fetch instead of iterating it? Here is my code
for(Tree t : assignedTrees) {
println t.treeName;
}
The above code will return the expected value.
assignedTrees is the set object
Set<Tree> assignedTrees = new HashSet<Tree>()
println assignedTrees will return
[Tree{id=null, treeName=Mango}]
Can I fetch the treeName instead of iterating?
You can fetch an object from a set by calling mySet.get(object). However, in your case you wish to fetch an object based on one of its attributes. The best way to do this is with a map - e.g.
Map<String, Tree> trees = new HashMap<>();
trees.put(treeObject.treeName, treeObject);
Tree myTree = trees.get("myTreeName");
Note that if you're putting your own objects into sets or maps, you must override the equals and hashcode methods, or very strange things will happen.
In general you can use lambda to find any/first element that fullfils any condition. For example:
Set<Integer> coolStrings = new HashSet<String>();
coolStrings.add("HEHE")
coolStrings.add("NOPE")
coolStrings.add("JP2GMD")
coolStrings.add("1234")
try{
String nice =
coolStrings.stream().filter(
(str) -> { return str.equals("JP2GMD") ||
str.equals("2137"); }
}).findFirst().get();
)
System.out.println("Yay, i found a REALLY cool string! : " + nice);
}
catch(NoSuchElementException e){
System.out.println("Not even one awesome string was found :(");
}
It will print "JP2GMD"
(I didn't compile it, there might be some minor syntax errors)
Working with Stream class is extremally handy (as for java standards)

"Simple" Trie Implementation

I need to implement a Trie (in Java) for a college project. The Trie should be able to add and remove Strings (for phase 1).
I have spent several hours each day (for the last few days) trying to figure out how to do this and FAILED miserably each time.
I require some help, the examples on the internet and my textbook (Data Structures and Algorithms in Java By Adam Drozdek) are not helping.
Information
Node classes I am working with:
class Node {
public boolean isLeaf;
}
class internalNode extends Node {
public String letters; //letter[0] = '$' always.
//See image -> if letter[1] = 'A' then children[1] refers to child node "AMMO"
//See image -> if letter[2] = 'B' then children[2] refers to internal node "#EU"
public TrieNode[] children = new TrieNode[2];
public TrieInternalNode(char ch)
{
letters = "#" + String.valueOf(ch);//letter[0] = '$' always.
isLeaf = false;
}
}
class leafNode extends Node
{
public String word;
public TrieLeafNode(String word)
{
this.word = new String(word);
isLeaf = true;
}
}
And here is the pseudo code for insert that I need to follow: (warning it is very vague)
trieInsert(String K)
{
i = 0;
p = the root;
while (not inserted)
{
if the end of word k is reached
set the end-of-word marker in p to true;
else if (p.ptrs[K[i]] == 0)
create a leaf containing K and put its address in p.ptrs[K[i]];
else if reference p.ptrs[K[i]] refers to a leaf
{
K_L = key in leaf p.ptrs[K[i]]
do
{
create a nonleaf and put its address in p.ptrs[K[i]];
p = the new nonleaf;
} while (K[i] == K_L[i++]);
}
create a leaf containing K and put its address in p.ptrs[K[--i]];
if the end of word k is reached
set the end-of-word marker in p to true;
else
create a leaf containing K_L and put its address in p.ptrs[K_L[i]];
else
p = p.ptrs[K[i++]];
}
}
I need to implement the following methods.
public boolean add(String word){...}//adds word to trie structure should return true if successful and false otherwise
public boolean remove(String word){...}//removes word from trie structure should return true if successful and false otherwise
I cant find pseudo code for remove, but if insert does not work delete wont help me.
Here is a image of how the Trie that I need to implement should look like.
I am aware that the Trie will still be inefficient if implemented like this, but at the moment I need not worry about this.
The book provides an implementation that is similar to what I need to do but doesn't use the end of word char ('$') and only stores the words without their prefixes in the child nodes http://mathcs.duq.edu/drozdek/DSinJava/SpellCheck.java
Constraints
I need to implement the trie in JAVA.
I may not import or use any of Java's built-in data structures. (ie. no Map, HashMap, ArrayList etc)
I may use Arrays, Java primitive Types and Java Strings.
The Trie must use a $ (dollar) symbol to indicate a end-of-word. (see the image below )
I may asume that now word containing the $symbol will be inserted.
I need to implement the Trie it in the same style as the book does.
Case of words doesn't matter ie. all words will be considered to be lowercase
The Trie should only store the end-of-word character and the characters applicable to a word and not the entire alphabet(like some implementations).
I do not expect anyone to do the implementation for me(unless they have one lying around :P) I just really need help.
First of all, I don't think you should make leaf nodes and internal nodes separate classes. I recommend making a universal node class with an isLeaf() method. This method would return true if a node has no children.
Here is some higher-level pseudocode for the functions you need to implement. For simplicity, I assume the existence of a method called getIndex() which returns the index corresponding to a character.
Insert(String str)
Node current = null
for each character in str
int index = getIndex(character)
if current.children[index] has not been initialized
initialize current.children[index] to be a new Node
current = current.children[index]
You can easily augment this pseudocode to fit your needs. For example, if you want to return false whenever insertion isn't successful:
Return false if the input string is null
Return false if the input string contains invalid characters
Now, here is some higher-level pseudocode for remove.
Remove(String str)
Node current = null
for each character in str
int index = getIndex(character)
current = current.children[index]
// At this point, we found the node we want to remove. However, we want to
// delete as many ancestor nodes as possible. We can delete an ancestor node
// if it is not need it any more. That is, we can delete an ancestor node
// if it has exactly one child.
Node ancestor = current
while ancestor is not null
if ancestor has 2 or more children
break out of loop
else if ancestor has less than 2 children
Node grandAncestor = ancestor.parent
if grandAncestor is not null
reinitialize grandAncestor.children // this has the effect of removing ancestor
ancestor = ancestor.parent
At a very high level, we follow the input string to the node we want to remove. After this, we traverse up the tree following parent pointers and delete every node with 1 child (since it is no longer needed). Once we reach a node with 2 children, we stop.
Like Insert, we can easily augment this pseudocode to return false whenever deletion isn't successful:
Return false if the input string is null
Return false if the input string contains invalid characters
Return false if the input string leads to a Node which doesn't exist
It is easiest to implement delete if your Node class has a parent field. However, it is possible to implement the method without parent points, but it is more difficult. You can see an example of the trickier implementation here.

Java - Recursion - Exception in thread "main" java.lang.StackOverflowError

i ran into an issue when trying to print out a list of file dependencies.
About the program:
Scans given *.c files for dependencies, more specifically looks for "#include "%"
Find those files and scans them for their dependencies recursively
All information is stored in a ConcurrentHashMap(key:String value:Linked List of Strings) theTable, where Linked List of Strings contains the list of dependencies.
After processing a certain file, i end up with the following hash table:
If I understand what the map output is saying, there is a cycle ( a #include loop ) in your header files.
i_50.h=[i_35.h, i_28.h, i_45.h, i_44.h, i_46.h],
....
i_35.h=[i_50.h, i_51.h]
That means that your dependencies are a graph and not a DAG. And that in turn means that a simple recursive walk will not work.
By the looks of it, you are attempting to do a graph walk, but for some reason your cycle detection / avoidance is not working, and your algorithm goes into "infinite" recursion.
After looking at the code, I think I can see where the problems are. In the first method, you check that a dependency has already been printed, and then set the entry in the alreadyPrinted map to say it has. But you then proceed to print it irrespective. Then in the second method you are (inexplicably) creating a new alreadyPrinted map each time you recurse to the first method. In other words, the logic of your cycle avoidance is broken.
Rather than fixing your code for you, I'm going to suggest that you go to your favourite "data structures and algorithms" text book and look up "graph traversal" in the index. Alternatively, here's an page I found in some online lecture notes:
http://underpop.online.fr/j/java/algorithims-in-java-1-4/ch05lev1sec8.htm
There's also stuff on graph traversal in Wikipedia, and other places. Google for "java recursive graph traversal", and try and find something that makes sense to you.
The general algorithm is something like this:
traverse(Node node):
traverse_0(node, new Set<Node>())
traverse_0(Node node, Set<Node> visited):
if (visited.contains(node))
return
visited.add(node)
for (Node child: node.children)
traverse_o(child, visited)
The only place where you test if a dependency has already been printed, is the first for loop. You should check in the second for loop too!
for (String d : dependencies) {
if (!alreadyPrinted.containsKey(d)) {
LinkedList<String> key = theTable.get(d);
if (key != null)
output += printDependencies(theTable, key, alreadyPrinted);
}
}
It is fairly easy to see that your algorithm recurses, as soon as some dependency looks like:
item: ...., item, ....
(I hear you say: "that cannot happen, because ...". Yet, the SO shows that either it did happen, or your stack is too small.)
By the way, you maintain the map "already printed", but it is nowhere used? This hints to a flaw in your implementation.
As you are maintaining some state (alreadyPrinted and output) I would recommend moving the state to instance-variabes and to use an object and no class-methods.
The problem was that my Graph traversal had cycles which I was not handling. The working code is provided below.
private static String printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, LinkedList<String> dependencies, ConcurrentHashMap<String, Boolean> alreadyPrinted) {
String output = "";
for (String d : dependencies) {
boolean isPrinted = alreadyPrinted.containsKey(d);
if (!isPrinted) {
output += " " + d;
alreadyPrinted.put(d, true);
}
}
for (String d : dependencies) {
LinkedList<String> key = theTable.get(d);
if (key != null) {
LinkedList<String> unvisited = new LinkedList<String>();
for (String filename : key)
if (!alreadyPrinted.containsKey(filename))
unvisited.add(filename);
if (unvisited != null)
output += printDependencies(theTable, unvisited, alreadyPrinted);
}
}
return output;
}
private static void printDependencies(ConcurrentHashMap<String, LinkedList<String>> theTable, ConcurrentLinkedQueue<String> toProcess) {
String output = "";
for (String current : toProcess) {
ConcurrentHashMap<String, Boolean> alreadyPrinted = new ConcurrentHashMap<String, Boolean>(); // Keeps track of dependencies already printed
output += current + ":" + printDependencies(theTable, theTable.get(current), alreadyPrinted) + "\n";
}
System.out.println(output);
}

Creating a for loop to do a to.String to my array list

Im currently making a shopping store application, I have 6 classes. 1 for products where it defines the fields for products in the store, another for the shopping basket, one for the GUI and the rest for listeners.
I need to be able to run a method that runs through an array list and running the to.String method on it and returning it as String. Here is what I have at the moment,
private ArrayList<OrderItem> basket = new ArrayList<OrderItem>();
public String createArrayText () {
for (int i = 0; i < OrderItem.size(); i++){
if (i == OrderItem.size() - 1){
return ordersText ;
}
}
}
ordersText is a variable I made at the top of my shopping cart class.
This was my first start at it however I'm getting a error on the .size and obviously missing some key components.
One thing Extra is that each item created is added to the array list, each item has a unique order number.
Arrays.toString(basket);
Is that what you're looking for? If not, you need to explain a little better.
You generally speaking loop over a List like this (Java 7, it's called enhanced for loop):
for (TYPE TEMP_NAME : COLLECTION) {
}
That's the overall syntax. TYPE is the type of item in the list, yours are Object's in the given code. TEMP_NAME is the temporary name you want each entry to be referred as. COLLECTION is the list/array/stack/queue or other Collection.
Concretely:
for (Object o : basket) {
// if basket contains 10 entries the line will run 10 times. each new run contains a different object with name o
}
Normally when building strings it's preferred to use StringBuilder. We can skip that as it's "only" performance that you gain from it. We'll do it with a regular String. So:
Create an empty string that will get longer and longer
Loop the collection/array/list
Append each object's .toString() to the string from 1)
e.g.
String myReturnString = "";
for (Object o : basket) {
myReturnString = myReturnString + " // " + o.toString();
}
return myReturnString;
Notes:
Your loop with an index is fine. You can do it that way too, if you want to.
The line of code that appends the string has a " // " separator between each entry. You can pick whatever you like. You can also simplify it to be myReturnString += " // " + o.toString();

How to print a list with a different separator from the comma?

I keep on copy-pasting the following in my programs. I'm wondering if anyone of you uses similar code, perhaps in a library to achieve the same.
#Override
public String toString() {
String ret = prefix;
boolean first = true;
for (Component child : children) {
if (!first) {
ret += " " + separator + " ";
} else {
first = false;
}
ret += child.getName();
}
return ret + postfix;
}
PS: One could use StringBuilder instead of String. Got that.
Apache commons provides a number of join methods in the StringUtils class.
This page also has a lot of interesting suggestions on the best way to implement such a method: http://snippets.dzone.com/posts/show/91
Nope. The only thing I can think of is it abstract that " " away into a final field in the toString() function. The reason that we don't have anything nicer is because the foreach construct doesn't care about the position, only that it will print sequentially.
That being said, avoid copy and paste at all costs. Make your own library if need be. Allow it to take a parameter of an interface which indicates if it is the first, and go from there.

Categories

Resources