I've got a basic binary search tree in Java. I'm trying to output the variable value, but all I get are addresses instead of the value itself. Also, can someone explain the relation between the code in my inOrderTraversal method and how it relates to the display() in my Node class even though I'm not calling it myself? All I'm calling in main is addNode and inorderTraversal.
The following is my code:
class Node {
int value;
Node leftChild;
Node rightChild;
Node(int value, String name) {
this.value = value;
this.name = name;
}
public int displayNode() {
return value;
}
}
InOrderTraversal Method:
public void inOrderTraverseTree(Node focusNode) {
if (focusNode != null) {
// Traverse the left node
inOrderTraverseTree(focusNode.leftChild);
// Visit the currently focused on node
System.out.print(focusNode + " ");
// Traverse the right node
inOrderTraverseTree(focusNode.rightChild);
}
}
Current Output: Node#7852e922 Node#4e25154f Node#70dea4e Node#5c647e05 Node#33909752 Node#55f96302
Desired Output: 5 10 15 20 25 30
I'm pretty familiar with C++, was just self-learning Java and ran into these peculiar issues.
I'm only getting addresses not values of the nodes
What is the link between inOrderTraversal and display()? I'm not even calling the display() method myself.
You're printing an object, not its inner value (in other words, you're calling toString() implicitly).
In order to print the value, you should get the value from Node object:
System.out.print(focusNode.displayNode() + " ");
Also I would recommend you to rename your displayNode() method to getValue(), as it is better explains what the method does.
And if you want your method to print something when calling System.out.println(object);, you should override toString() method in Node class:
#Override
public String toString() {
return this.value;
}
Then your code System.out.print(focusNode + " "); will display the node's value instead of object's address im memory.
Related
I am new to using recursion for my methods. I tend to steer away from them for quite a few reasons. However, for a project, it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph.
Since I am not too well versed in recursion, I don't understand why I am getting the following error.
This method must return a result of type LinkedList.Node
The code I have currently is:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
DFSTime(node.nextNode);
}
}
It is unfinished code since I still need to implement some logic, however, I don't understand how to eliminate the error. Is there something very basic that I am missing?
The reason of the compilation error is pretty trivial. The compiler clearly tells that didn't provide the result to return for all possible cases.
The more important is that your current approach is not correct.
it seems to easier to have a recursive method instead of a looping one since I am trying to do Depth First Traversal for a Graph
There are crucial things to consider:
Field nextNode is very suspicious. If each Node holds a reference pointing to a single node only, in fact the data structure you've created by definition isn't a Graph, but a Singly linked list. And doesn't make sense to implement DFS for a list. Every node should point to a collection of nodes, no to a single node.
You have to distinguish somehow between unvisited nodes and nodes that are already visited. Or else you might and up with infinite recursion. For that, you can define a boolean field isVisited inside the Node, or place every visited node into a HashSet.
Since you've chosen to create a recursive implementation of DFS, you don't need to create a stack. It's required only for iterative implementation.
Don't overuse global variables. I guess you might want to be able to check whether it is possible to reach different airports of destination without reinstantiating the graph.
Use getters and setters instead of accessing fields directly. It's a preferred practice in Java.
Your method might look like this (it's not necessary that element should be of type String it's just an illustration of the overall idea):
public Node DFSTime(Node node, String destinationAirport){
if(node == null || node.isVisited()) {
return null;
}
if (node.getElement().equals(destinationAirport)) {
System.out.println("The destination airport was found");
return node;
}
node.setVisited(true);
for (Node neighbour: node.getNeighbours()) {
Node result = DFSTime(neighbour, destinationAirport);
if (result != null) return result;
}
return null;
}
And the node might look like this:
public class Node {
private String element;
private List<Node> neighbours;
private boolean isVisited;
public Node(String element, List<Node> neighbours) {
this.element = element;
this.neighbours = neighbours;
}
public void setVisited(boolean visited) {
isVisited = visited;
}
public boolean isVisited() {
return isVisited;
}
public void addNeighbours(Node neighbour) {
neighbours.add(neighbour);
}
public String getElement() {
return element;
}
public List<Node> getNeighbours() {
return neighbours;
}
}
You should have a default return statement at the end of the function after the closing of the else.
In methods conditional blocks (if-else), you need to make sure you are returning appropriate Type from all conditional statements, so that there is no compile-time error. In your case, else block is recursively calling DFSTime(..) without returning anything.
You might want to return reference which gets called via recursive call, something like below:
public Node DFSTime(Node node){
if(node == null){
System.out.println("No path found");
return null;
}
else if(node.element.equals(destinationAirport)){
return node;
}
else{
stack.push(node);
Node node = DFSTime(node.nextNode);
return node;
}
}
I am working on a code that puts new elements on MyStack if they are unique. I had to copy and paste the node starting code, so I'm having a bit of trouble with an issue. I keep getting two error messages, even after trying various workarounds and I'm not really understanding why. I've even tried using some helper functions I've previously made that have worked before so I'm extra confused.
The two errors I consistently get are:
-cannot infer type arguments for MyStack.Node (actual and formal arguments differ in length)
-constructor node cannot be applied to given types. Required, no arguments, found: anything,
Here's my code:
public class MyStack<Anything>
{
private Node first, last;
private class Node<Anything>
{
Anything item;
Node next;
}
public boolean contains(Anything value)
{
for (Node curr = first; curr != null; curr = curr.next)
{
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
public void add(Anything value)
//method that adds a new value to the end of the list
//COMPLETE
{
Node temp = first;
while(temp.next!=null){ //finds the end
temp=temp.next;
}
temp.next=new Node(value, null); //assigns new value
}
public void enqueue(Anything info){
if (this.contains(info)==true) { //if the info is already present
System.out.println("the stack already contains this value");
return;
}
//if we actually need to add the info
if (first == null) { //if there is nothing in the stack
Node temp= first;
first = new Node<>(info,temp);
first = temp;
return;
}
if (first != null) { //if there is already stuff
Node temp = first;
while (temp.next == null)
{ Node newNode= new Node<>(info, temp);
temp.next = newNode;
}
return;
}
}
}
As #Andreas already pointed out, Node needs a constructor.
There are a few other flaws in your Code:
Use Generics
With your Code, you can only store Objects of the class Anything, what strongly limits its reusability. Use a generic instead and you can reuse this class for many more purposes.
Linked List
I suggest, you use the paradigm of a double-linked-list. That way you do not need to find the last Node to add something to the Stack. Node now has a pointer to its previous and next element.
Use the last Object
You have the object last but never use it. To find out, whether the current object is the last one you compare the value to null. This has the effect, that storing a null value will break your List. Instead compare to the Object last, this object is unique and guarantees you, that you are at the end of the list. Both first and last are Nodes that do not contain a value and are simply used to mark the start/end of your List.
Adding elements
Using the changes above, the code in the Method enqueue(T value) becomes significantly simpler: You just check whether contains(value) and decide whether you add the value to the List or not.
All these changes applied result in following code:
public class MyStack<T extends Object> {
private Node first, last;
public MyStack() {
first = new Node(null, null, null);
last = new Node(null, null, first);
first.next = last;
}
private class Node {
T item;
Node next;
Node previous;
public Node(T item, Node next, Node previous) {
this.item = item;
this.next = next;
this.previous = previous;
}
}
public boolean contains(T value) {
for (Node curr = first.next; curr != last; curr = curr.next) {
if (value.equals(curr.item)) {
return true;
}
}
return false;
}
/**
* method that adds a new value to the end of the list
*/
public void add(T value)
{
Node secondLast = last.previous;
Node added = new Node(value, last, secondLast);
secondLast.next = added;
last.previous = added;
}
/**
* only adds value if it is not already contained by the Stack
*/
public void enqueue(T value) {
if (this.contains(value) == true) { // if the info is already present
System.out.println("the stack already contains this value");
}
else {
add(value);
}
}
public static void main(String[] args) {
MyStack<String> test = new MyStack<>();
test.add("foo");
test.add("bar");
test.add("baz");
System.out.println(test.contains("bar"));
System.out.println(test.contains("new"));
test.enqueue("baz");
test.enqueue("MyStack");
}
}
Naming
As you may have noticed, in my explanation I called this class a List. This is because it fulfills more of the characteristics of a List. A Stack usually only provides the methods push to put something at the top of the Stack and pop to remove and return the topmost Object. Optionally peek can return the topmost Object, without removing it from the Stack.
Also consider renaming the method enqueue: enqueue is used in Queues (obviously) and Queues do not forbid to add two equal Objects. So the name is misleading. I would call this method something like addIfNotContaining.
In my Opinion you should name this class to be a List and add a method get(int i) to get a specific element at a position. Naturally adding some other methods like size ect. to comply with a standard List. But I assume you already had, but did not post them because they are not related to your problem.
Multithreading
This Class is far from threadsave. But I let you figure out yourself how to make it threadsave if needed.
I have a Node model like below with list of child nodes:
class Node {
private String name;
private List<Node> childNodes;
public Node(String name, List<Node> childNodes) {
this.name = name;
this.childNodes = childNodes;
}
public Node(String name) {
this(name, new ArrayList<>());
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public List<Node> getChildNodes() {
return childNodes;
}
public void setChildNodes(List<Node> childNodes) {
this.childNodes = childNodes;
}
public void addChildNodes(Node childNode) {
this.getChildNodes().add(childNode);
}
}
What I am going to do is checking if a loop is produced when adding a child node to a parent node. Loop here means a child node has the same name as its direct or indirect parent. And when the loop is detected, I would like to print out also which nodes are content in this loop. What I have done sofar is:
private static void findLoop(Node currentNode, String orginalNodeName, String visitedNode) {
if (currentNode != null && !currentNode.getChildNodes().isEmpty()) {
for (Node childNode : currentNode.getChildNodes()) {
visitedNode = visitedNode + "->" + childNode.getName();
if (childNode.getName().equals(orginalNodeName)) {
System.out.println("Loop is detected: " + visitedNode);
}
findLoop(childNode, orginalNodeName, visitedNode);
}
}
}
My idea is looping through all the child nodes, start from the node that I want to check, and compare if the current node has the same name as the original starting Node, if yes then a loop is detected.
It works but I can not print the content of the loop correctly, because it loop through all of the possible child nodes of a parent node, ex:
parentNode
node1 node2
childNode1 childNode2
parentNode childChildNode2
It printed: parentNode->node1->node2->childNode2->parentNode and what I would like to print is : parentNode->node2->childNode2->parentNode
Can anyone give me some hint here? Thank you so much!
Since you are pretty close to the result that you would like to get, here are several hints for you on how to complete the task:
findLoop needs to return boolean - otherwise you would not know when to stop iterating at the higer levels of recursion
visitedNode needs to be a List<Node> - otherwise you are stuck with a single item's name
When findLoop inside for(...) returns true, method returns true immediately - this makes sure that a positive does not get ignored
Finally, don't forget that findLoop needs to start with the child node, and loop for the parent node, not the other way around.
I am writting a program that performs an a star search throughout a map. I have created a class that hold all the nodes of the map.
public Node {
Node up_node, right_node, down_node, left_node;
}
public class Star {
public static void main(String args[]) {
Node a=new Node();
Node b=new Node();
Node h=new Node();
Node here=new Node();
Node[] NextNode;
NextNode = new Node[10];
for(int i=0;i<10;i++) {
NextNode[i]=new Node();
}
int j=0;
a.up_node=h;
a.right_node=b;
b.left_node=a;
h.down_node=a;
//if certain conditions are met
NextNode[j].here_node=a.up_node;
//what i was hoping to do is copy the node a.up which is h
}
}
into NextNode[0] in this case. However it keeps returning a memory address of some sort : test.Node#10b28f30: test being the name of the package, please help!
#override the toString() method to display the internal property of your class.
By default, java display the full class name#hashCode value.
Variables in Java are object references not actual objects. NextNode[j].here_node = a.up_node; will make NextNode[j].here_node and a.up_node point to the same object. Is this not what you want?
If you wanted to make a completely new copy of the object, then you can implement that in the Node class:
public class Node {
Node up_node, right_node, down_node, left_node;
public Node clone() {
Node ret = new Node();
// copy the properties
ret.up_node = this.up_node;
...
return ret;
}
}
Now
NextNode[j].here_node = a.up_node.clone();
will make a copy (although it's only a shallow one -- the copy will point to the same objects via its fields as opposed to copies of them).
I assume your confusion about the code returning "an address" comes because you tried to print a node, e.g.
System.out.println(a.up_node);
You'll get something like test.Node#10b28f30, but try
System.out.println(NextNode[j].here_node);
and you should get exactly the same string, indicating that they're pointing to the same object.
To get something nicer, you must override Node's implementation of toString(). Here's an example that will give each Node a unique number:
public class Node {
Node up_node, right_node, down_node, left_node;
// how many nodes were created
private static int count = 0;
// the number of this node
private int number;
public Node() {
// increment the number of nodes created
++Node.count;
// assign that number to this node
this.number = Node.count;
}
public String toString() {
return "Node #" + this.number;
}
}
We know that every class that we write are child of Object class. When we print a child of an Object it prints its toString() method. By default it is a hashed value of memory location. So it prints sort weird things. if we #overriding toString method to return something more meaningful to us then we can solve this problem. If we can name our node class someway I think we can keep track of them easily
class Node(){
String nameOfNode;
//contractor to keep track of where it goes.
public Node(String a){
nameOfNode=a;
}
//when we will print a Node it is going to print its name
public String toString(){
return nameOfNode;
}
}
Then it will print the name of the node. And it will stop showing that weird memory address.
and replace your new Node() with distinct name new Node("a name")
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().