How to display a LinkedBinaryTree - java

I need to understand the best way to display my linkedBinaryTree. right noe the driver is passing in integers as elements to each node of the tree, For the toString i have tried the following snippet of code but all it returns is for instance is javafoundations.ArrayIterator#ca0b6.
public String toString() {
String thing = "BinaryTreeNode: ";
if (root.getLeft() != null ) {
thing += root.getLeft().toString()+" ";
}
if (root.getRight() != null) {
thing += root.getRight().toString();
}
thing += "}";
return thing;
}

You just need to override the method
public String toString()
in the node class you are using. Doing that will replace the useless representation to a more sense one.
Of course you need to understand which is your data object inside the tree (I don't know if a node is a value of if it contains a value) so that you'll be able to call the correct toString method.
In any case you don't need to explicitly call it whenever you are using string concatenation operator eg "" + root.getLeft()

Related

Performance penalty when using Java varargs method with no arguments

Suggest the following Java class:
/** Utility class for working with DOM nodes.
*/
public class DomNodes {
public static boolean isElement(Node pNode, String pElementName, String... pAttributes) {
if (pNode.getNodeType() == Node.ELEMENT_NODE) {
final Element e = (Element) pNode;
final String uri = e.getNamespaceURI();
if (uri == null || uri.length() == 0) {
if (pElementName.equals(e.getLocalPart())) {
if (pAttributes == null || areAttributesMatching(pNode, pAttributes)) {
return true;
}
}
}
}
}
}
Now, suggest the following two uses of that class:
isElement(node, "foo");
isElement(node, "foo", "attribute0", value0, "attribute1", value1, "attribute2", value2);
It is obvious to me, that the second invocation depends on the construction of a string array. In other words, there is a small performance penalty for the construction of that array.
The first invocation, however, isn't obvious: The compiler could implement this by passing a newly constructed array with no elements. However, it might just as well pass the value null, or a constant array.
In the former case, I could help the compiler by adding a method
isElement(Node pNode, String pElementName). Question: Would you recommend that?

toString method for a doubly linked list using recursion

public String recursiveToString()
{
DoubleLinkedListNode<T> current = first;
String list = "";
if(current == null)
{
return "";
}
else
{
list += current.info + ", ";
current = current.next;
return list + recursiveToString();
}
}
It is supposed to print out the list when I run the code but it just crashes every time it runs. This is everything that I've tried to do so far.
First off you'll want to pass the current position in the list back into the function each time, so change your signature to this:
public String recursiveToString(DoubleLinkedListNode<T> current)
Then alter your code a bit so it uses that and continues to pass it down, the list variable is also unnecessary, the recursion will take care of concatenating everything:
public String recursiveToString(DoubleLinkedListNode<T> current)
{
if(current == null)
{
return "";
}
else
{
return current.info + " " + recursiveToString(current.next);
}
}
If you would like to do it without changing the signature of the function, just rename the function I have above and create the definition for your parameterless function like so:
public String recursiveToString()
{
return aboveFunction(first);
}

Recursive tree encryption method using dfs

This problem is not for an assignment, although it's a somewhat typical "assignment-like" problem that I'm trying to solve in a different way.
I want to write a method that will recursively go through a binary tree using a depth-first search algorithm to find a match for a character. Once it finds the matching character, I want it to return a string that maps the position of the character in the tree using 0s and 1s. "001",for example, would indicate that the character is found by going to the left node of the root node, the left node of that node, and then to the right node of that node.
Here is the code I have so far:
private static String encryptSearch(char c, BinaryNode curNode, String result)
{
char data = (char) curNode.getData();
if (data != c)
{
if (curNode.hasLeftChild())
{
result = result + "0";
encryptSearch(c, curNode.getLeftChild(), result);
}
if (curNode.hasRightChild())
{
result = result + "1";
encryptSearch(c, curNode.getRightChild(), result);
}
result = result.substring(0, result.length()-1);
}
return result;
}
The method is initially sent the character to be searched for, the root node, and null for the result. This method returns nothing except 0s. I think there are multiple problems with my code, but the largest one is that when the search reaches a leaf node, it returns. I've been unable to think of a way around this problem while still returning a string. I could easily write a void method that acts on the result string as an external variable, but I don't want to do that for the purpose of the exercise. Any help is appreciated!
Use the mutable StringBuilder instead of String. Also there should be a way to know that you got the result from left one (if any) before searching right one. So I suggest following changes.
private static boolean encryptSearch(char c, BinaryNode curNode, StringBuilder result) {
char data = curNode.getData();
if (data != c) {
boolean found = false;
if (curNode.hasLeftChild()) {
found = encryptSearch(c, curNode.getLeftChild(), result);
if (found) {
result.insert(0, "0");
return true;
}
}
if (curNode.hasRightChild()) {
found = encryptSearch(c, curNode.getRightChild(), result);
if (found) {
result.insert(0, "1");
return true;
}
}
return false; //no result
}
return true;
}

Returning an inorder string of a Tree

EDIT This has been resolved by using StringBuilder as suggested in this thread. Thank you :D
Hello,
I have a tree and am trying to return a String of the content in order.
I can currently print out the tree with something like this:
public void inOrder() {
if (left != null) left.inOrder();
System.out.print(content + " ");
if (right != null) right.inOrder();
}
But what I want to do is return the String (rather than print out each nodes content while recursing) and I can't work out how to do it. I tried many variations of the code below, but it just returns the last element it finds in the recursion.
public String inOrder(String string) {
if (left != null) left.inOrder(string);
string += content;
if (right != null) right.inOrder(string);
return string;
}
Strings are immutable in java. You are not concatenating new String to old one, you are creating new String and make string variable point to it. Result is that you have many unrelated Strings and string variable points to them in various points in time.
You need to pass mutable object to your function such as StringBuilder. This solution have additional advantage that it's much more efficient because you are avoiding unnecessary Object allocations.
If you want to do this with String concatenation, your second example nearly works - the problem is only that you are throwing away the results of the recursive calls.
/**
* creates an Inorder-string-view of this tree and appends it to the given string.
* #return the new String.
*/
public String inOrder(String string) {
if (left != null)
string = left.inOrder(string);
string += content;
if (right != null)
string = right.inOrder(string);
return string;
}
But this is (for larger trees) horrible inefficient, since each += in fact creates a new String, copying the characters of string and content - thus each content string is in fact copied the number of later nodes (in inorder sequence) times (+1). A slightly better way would be this:
public String inOrder() {
String leftS; String rightS;
if (left != null)
leftS = left.inOrder();
else
leftS = "";
if (right != null)
rightS = right.inOrder();
else
rightS = "";
return leftS + content + rightS;
}
or a bit shorter:
public String inOrder {
return
(left != null ? left.inOrder() : "") +
content +
(right != null ? right.inOrder() : "");
}
Now each content string is only copied the number of nodes above it times (+1), which for a "usual" (not extremely unbalanced) tree is much smaller. (This variant could easily be parallelized, too.)
But in fact, the StringBuilder version is normally the preferred one, since it copies each content string only one time (when appending it to the StringBuilder), and maybe some more times during internal resizes of the StringBuilder (so if you can estimate the final size before the actual conversion, create a StringBuilder big enough).
Strings are immutable in Java and when you add something to a String, a new object is created. Thus, the change is not visible outside the scope of the method.
Try a StringBuilder instead of String:
public StringBuilder inOrder(StringBuilder string) {
if (left != null) left.inOrder(string);
string.append(content);
if (right != null) right.inOrder(string);
return string;
}
You could read here: http://www.javaworld.com/javaqa/2000-05/03-qa-0526-pass.html to understand the way Java passes arguments to methods and why Strings immutability is an issue in your original code.
Regards,
Sorin.
Java is pass by value. A reference to an object passed to a method can't be changed by this method. You can change the content of an object, but you can't do that with Strings, because they are immutable (their content can't change).
The line
string += content;
affects a new String object to the string variable. It doesn't change the content of the original String object.
You need to pass a StringBuilder instance to your method, and append to this StringBuilder:
public String inOrder() {
StringBuilder strinBuilder = new StringBuilder();
postOrder(stringBuilder);
return stringBuilder.toString();
}
private void postOrder(StringBuilder stringBuilder) {
if (left != null) left.postOrder(stringBuilder);
if (right != null) right.postOrder(stringBuilder);
}

Java linked list printing

Is there any way to abbreviate the print() and toString() into one function in a Java linked list function or is there any explanation as to why someone would format this way?
public void print() {
System.out.println(this.toString());
}
#Override
public String toString() {
String display = "";
LinkedList current = this;
while (current != null) {
display += new Integer(current.head).toString() + ",";
current = current.tail;
}
display = display.substring(0, display.length()-1);
return display;
}
I would use StringBuilder, because it's more memery efficient :
public void print() {
System.out.println(this.toString());
}
#Override
public String toString() {
StringBuilder display = new StringBuilder();
for(Integer current: this) {
display.append(current).append(',');
}
return display.toString().substring(0, display.length()-1);
}
No. There is no way to do that in Java 6. Future Javas? Don't know. :-)
The way you are doing it, it's pretty much the more concise way to achieve it.
The code you've shown is very amateurishly written. Concatenating into a String is just the main red flag.
If you're not too concerned about performance, you could stringify the whole list in one line of code:
return Arrays.deepToString(toArray());
Of course this depends on elements of the list having sensible toString() methods of their own.
You could add a toString() to the class representing a node of your linked list:
class Node<T> {
T value;
Node<T> next;
public String toString() {
return value + (next != null ? ", " + next : "");
}
}
And then implement the toString() of your linked list as follows:
public class LinkedList<T> {
Node<T> head;
public String toString() {
return "[" + (head != null ? head : "") + "]";
}
}
This way it will print the nodes recursively.
The print() function in turn can be replaced by just printing this since System.out.println(object) under the hoods returns String.valueOf(object) which in turn under the hoods returns object != null ? object.toString() : "null".
public void print() {
System.out.println(this);
}
The reason it's done like this is that if you want to write a number of child classes which report themselves as Strings in different ways, you only have to override the toString() function on each, not the toString() and the print() function. If you want print() and toString() to have different functionality there is no reason why you can't override just print() to make it not call toString().

Categories

Resources