I'm migrating from C to Java and I'm having difficulties with recursion, specially because in Java you can't pass an argument by reference.
What I'm looking is not a solution/trick to force Java pass an argument by reference, but the recommended way to solve such a problem in Java.
Let's take the recursive node insertion in a binary tree:
void nodeInsert(Node n, int a) {
if (n == null)
n = new Node(a);
...
}
In C, by the end of the execution, the node n in the tree would point to the newly created node. In Java, however, n will still be null (because n is passed by value).
What is the suggested Java approach for such problems?
Some approaches I already tried:
Using a static object to keep track of the parent (issue complicates when using generics).
Passing the parent node as part of the function. It works but complicates the code a bit and doesn't look as a good solution.
Creating an additional member pointing to the parent node but this is not a good solution, as it increases the space required by O(n);
Any advice is welcome.
In Java instead of using reference variables, we use return values and assign it to the variable that has to be changed.
Node nodeInsert(Node n, int a) {
if (n == null){
n = new Node(a);
return n;
}
else
{
....
return nodeInsert(n,a); //this is how a recursion is done.
....
}
}
If you need more on recursion http://www.toves.org/books/java/ch18-recurex/ will teach you right.
A common way to implement is to maintain the node relationships inside the node itself. Quite a lot of examples can be found in implementations of various JDK datastructures. So the Node is the container for the value and contains references to other nodes, depending on the data structure.
If you need a child->parent relationship between nodes, the Node class would look like
class Node<T> {
T value;
Node parent;
}
In case of insert, you create a new node, set the parent reference to the original one, and return the new Node as a result (this is optional, but not uncommon to do, so the call has a handle of the new child)
Node<T> insert(Node<T> parent, T value) {
Node<T> child = new Node<>();
child.value = value;
child.parent = parent;
return child;
}
And yes, this adds a minor overhead of 4 bytes per Node (or 8 bytes, on 64bit JVMs without compressed pointers)
I propose the following solutions:
Implement a method in class Node that adds a child node. This makes use of the OO-possibility to encapsulate data and functionality together in a class.
Change nodeInsert to return the new node and add it to the parent in the caller (also mentioned in comments). The responsibility of nodeInsert is to create the node. This is a clear responsibility and the method signature shows what the result of the method is. If the creation is not more than new Node() it might not be worth to have a separate method for it.
You can pass a holder object that in turn references your new Node object
void nodeInsert(AtomicReference<Node> r, int a) {
if (r.get() == null)
r.set(new Node(a));
...
}
Or you could pass an array with space for one element.
After months posting this question, I realized yet another solution that is, in fact, already contemplated in java design patterns but not mentioned here: Null Object Pattern.
The downside is that each null occupies memory (in some cases, like large Red-Black trees, this could become significant).
Related
I've grown acostumed to use c++ pass by reference and now I'm starting to code more in Java. When solving a problem at leetcode I faced a problem: I tried to use this piece of code so I didn't have to rewrite this three lines often.
public void copyAndMoveNodes(ListNode tail, ListNode nodeToCopy) {
tail.next = new ListNode(nodeToCopy.val);
tail = tail.next;
nodeToCopy = nodeToCopy.next;
}
I was expecting it to work similarly this in c++:
void copyAndMoveNodes(ListNode* &tail, ListNode* &nodeToCopy) {
ListNode newNode = new ListNode(nodeToCopy.val);
tail->next = &newNode;
tail = tail->next;
nodeToCopy = nodeToCopy->next;
}
But I discovered I passed just the copy of the objects' references in java as writen in the first piece of code.
Is it possible to rewrite this in Java to work similarly? I use this sequence of three commands many times and I don't want to write them every time, it makes the code more confusing.
The solution is an additional return value - for a mechanical translation.
param = f(param, x);
Very ugly when having two references:
a void method with a parameter ListNode[]
a void method with a parameter Pair<ListNode, ListNode>
Best would be give a Stream a try. On collection classes no problem, on node classes holding a next field, it can still be done as:
Stream.iterate(rootToCopy, node -> node.next != null, node -> node.next)
.forEach(node -> { ... });
Even if it would be on a Pair of nodes or such.
So my conclusion: switch to the java collection classes and operate on entire lists
using .stream(). Knowing both sides C++ with the power of references, and java, I do not find it hard to have the more abstract style in java: performance still okay, readability fine, writability needing excercise, expressiveness and compactness excellent.
Porting the software in the first stage could be done best by inlining the method's code.
One apology for java: by language design f(x) will never change the variable x to
improve software quality / code checkers.
I need to create a recursive copy method for a binary search tree from scratch for an assignment of mine. The method should copy each item in a given BinarySearchTree object to the calling BinarySearchTree object. Only problem is that the method must be a void and everything I've looked up on this subject seems to utilize different return types to get this done.
I don't really know how to even start with something like this, all I have is the prettymuch empty shell of the method and it's wrapper. I'm not sure if the parameters in the private method are correct but it was my best guess as a start.
public void copy(BinarySearchTree<E> bst2){
copy(bst2, root, bst2.root);
}
private void copy(BinarySearchTree<E> bst2, Node node1, Node node2){
}
I'd appreciate any and all help.
Thanks!
Immediate thought is (rough pseudocode ahead):
class Tree {
//stuff in the tree with a root node, etc...
copyTree(Node parentTreeNode, Node copyTreeNode) {
if(copyTreeNode == null)
return;
parentTreeNode = clone(copyTreeNode) //clone just copies the node's values into the node.
if(copyTreeNode.leftChild != null) {
parentTreeNode.leftChild = new Node();
copyTree(parentTreeNode.leftChild, copyTreeNode.leftChild);
}
if(copyTreeNode.rightChild != null) {
parentTreeNode.rightChild = new Node();
copyTree(parentTreeNode.rightChild, copyTreeNode.rightChild);
}
}
}
And you would just call this with the two root nodes and let it recurse and it builds the tree for you.
So, if the base case gets triggered (the current node is null) then you skip that node by returning and move on in the recursion process (the base case is important in recursive techniques, otherwise you get infinite recursion). So, we start with the root node, copy it (if it's not null), and then move to the left subtree, assuming it's also not null. We pause in this method, call the method on the subtree, which "pauses" there and causes on the left.... When it returns back all the way down, each place it had "paused" resumes, moving to the right child on each of those nodes with the same procedure. Once the left subtree recurses on itself, we resume in the top node and move to the right subtree to do the same thing there (just like it did in all the children nodes, recursively). When it's all done, it just returns normally.
Recursion isn't particularly difficult, but it does take some practice to understand at first.
This is a rough idea and hasn't been tested, but that's roughly how I'd do it. It's probably worth noting that this style of handling it won't guarantee that the trees are the same if the main tree already had data in it, or you handed a node other than the root node. But it would be the same from below that node.
Whenever Collection#addAll is called, it creates a copy of the argument list and then attaches it to the collection on whom addAll was called.
Below is the code for case I :
if (parentData != 0) {
if (nodeParentMap.get(parentData) != null) {
nodeParentMap.put(newNodeData, parentData);
//Creates new Nodes' parent and assigns its next to its parent, in that way I get the parents' linked list
Node parent = Node.build(parentData);
parent.next = parentListMap.get(parentData);
parentListMap.put(newNodeData, parent);
}
} else {
//Code for root
nodeParentMap.put(newNodeData, parentData);
parentListMap.put(newNodeData, null);
}
Here its takes N iterations to find Nth parent.
Below is the code for case II:
if (parentData != 0) {
if (nodeParentMap.get(parentData) != null) {
nodeParentMap.put(newNodeData, parentData);
//Here all the parents of a node are present in arrayList #parents,
//so that I can fetch parent in O(1) as I know the index
ArrayList<Integer> parents = new ArrayList<>();
parents.add(parentData);
parents.addAll(parentListMap.get(parentData));
parentListMap.put(newNodeData, parents);
}
} else {
//Code for root
nodeParentMap.put(newNodeData, parentData);
parentListMap.put(newNodeData, new ArrayList<>());
}
But in case II when ArrayList#addAll is called, it creates copy of the list passed and then attatches it. So, Is there a way to execute ArrayList#addAll with calling System#arrayCopy?
Thank you.
In general, you should not care. The difference will be unnoticeable unless you run this code millions of times. You should write your code as cleanly as possible, if possible, and make it show your intent. Do you have a performance issue? Have you profiled your code and the profiler showed you that you're spending a lot of time in copying the array elements?
Measure, don't guess. You need a way to tell there is an issue. And you need a way to tell whether it is gone after a code change.
Could you perhaps change your algorithm if there's so much duplicate data and so much element copying that you maybe could use a more efficient structure or algorithm? For example, you could use Iterables.concat() of Google Guava. The resulting code will be shorter, states your intent very cleanly and does not copy anything - the underlying List will contain a reference to the original data structure and will only get it lazily. Beware that if this is massively chained, you didn't actually help yourself...
If after all this you still think you need to avoid the double array copy anyway, what stops you from doing this?
List<Integer> tempParents = parentListMap.get(parentData);
List<Integer> parents = new ArrayList<>(tempParents.size() + 1);
parents.add(parentData);
for (Integer i : tempParents) {
parents.add(i);
}
Note that performance-wise, this code will generally be comparable to just calling addAll() since in the ArrayList's overridden implementation of addAll() there's no iteration, just hard array copying which is intrinsified in the JVM and highly optimized. The above version will therefore only be useful for short lists (probably) or to solve a memory issue, not a performance one as the iterative version does not require any extra temporary memory while the copying one from addAll() does.
I'm coding a lexical analyzer in java and need to look backwards or forwards easily in a list of custom datatypes (my tokens). I've tried saving the next and previous item as a copy, but then I figured out that I need to look arbitrarily far ahead or back. I then tried to use an index, but it was beyond unpleasant to debug that since I had to think about decreasing, increasing and getting the current position in a pinch (I even had the objects store an int of where they were at) all the while keeping within range of the list, so it was an ugly, hard to read mess of spaghetti code too at that.
I then looked into linked lists, but they don't quite work like I want them too. I want a node and I want to be able to look ahead for two or three positions, or back, and I didn't really find any good tools for that at that place.
Right now, I'm trying out iterators but I have the same problem as with indexes: I have to decrease and increase back again to where I was at since next() moves the cursor instead of just "peeking ahead".
I'm thinking of coding my own linked list and just hitting node.next().next() if I want to go two steps forward, or a loop repeatedly hitting it if I want to go longer than that. Is there any built in way in Java saving me from this?
You're getting spaghetti code because you're not following SoC. One way to help yourself is to create a specialized collection class that implements functions which, for your problem domain, hide the ugly particulars of array navigation such as tracking the current position, iterating N steps back and forth, "peeking" back and forth, etc.
There are a hundred ways to do this but in my code sample below I chose to compose with rather than extend the ArrayList<> class. I chose ArrayList<> because of its random access capabilities and chose not to extend to help stay away from manipulating the ArrayList<> directly from client code and getting back into a spaghetti mess. I wasn't considering performance but as it happens that ArrayList<>'s random access functions are mostly O(1) rather than O(n) which you would get if you used an iterator or linked list. With those collection types you would also be forced to traverse through the collection just to peek at an object which hurts performance further and also makes implementation that much harder.
Here is a link to an Ideone implementation of my suggested solution. It is a bit different from the code shown below due to the complexities imposed by an online Java compiler but the code is easily accessible and fully executable.
Code sample notes: This is a full, working sample which contain three classes necessary to demostrate the concepts. There is a class to hold the main function which demonstrates usage of the collection class and also acts as a poor-man's unit test. There is a POJO-style class to represent a node or token and finally the utility class which exposes a specialized set of functions, or API. The code is very basic and naive. There is no error or bounds checking of any kind but it demonstrates my suggestion fairly well, IMHO.
To the code! Here is the main function which initializes the NodeList with an arbitrary, Java-like line of code and then proceeds to peek and move in the token list. Note that there is no variable needed in the client code to track what's going on. The navigation is all handled within the NodeList class. The client code's concerns now do not include that ugliness.
import java.util.*;
import java.io.*;
public class TestNodeList {
public static void main(String[] args) {
// usage: basic initialization
NodeList nl = new NodeList();
nl.add(new Node("someUtilObj"));
nl.add(new Node("."));
nl.add(new Node("print"));
nl.add(new Node("("));
nl.add(new Node("myIntValue"));
nl.add(new Node(")"));
nl.add(new Node(";"));
nl.print();
// usage: using the API, moving and peeking
nl.peekAhead(1).print();
nl.peekAhead(2).print();
nl.peekAhead(3).print();
nl.moveAhead(2).print();
nl.getCurrentNode().print();
nl.peekBack(2).print();
}
}
This is the implementation of the specialized collection with some fields and functions I assume would be useful for your lexical analysis. Again, it is quite bare but covers the more important concepts.
public class NodeList {
private ArrayList<Node> nodeList = new ArrayList<Node>();
private int currentNodeIndex = 0;
public void add(Node node) {
nodeList.add(node);
}
// Node is private/read-only - currentNode should only be set by internal operations
public Node getCurrentNode() {
return nodeList.get(currentNodeIndex);
}
// moving back and forth
public Node moveAhead(int count) {
currentNodeIndex += count;
return nodeList.get(currentNodeIndex);
}
public Node moveBack(int count) {
currentNodeIndex -= count;
return nodeList.get(currentNodeIndex);
}
// peeking back and forth
public Node peekAhead(int count) {
return nodeList.get(currentNodeIndex + count);
}
public Node peekBack(int count) {
return nodeList.get(currentNodeIndex - count);
}
public void print() {
for (int i=0; i<nodeList.size(); i++) {
System.out.print(nodeList.get(i).getToken());
}
System.out.println("");
}
}
Other functions to consider implementing for a better, cleaner API:
peekNext() - same as peekAhead(1) but w/o the magic number. I would think that this would also be the most frequently called function in your specialized collection so it makes sense to have a shorter, cleaner version of the operation than peekAhead(1)
peekPrev() - same as peekBack(1) but w/o the magic number
moveNext() - same as moveAhead(1) but w/o the magic number. This would also be a frequently called function in your API and a cleaner version of moveAhead(1)
movePrev() - same as moveBack(1) but w/o the magic number
peekAt(int) - Peek at an element at a specific index in the collection
jumpTo(int) - Move current position to an element at a specific index in the collection
moveFirst() - Resets your current position to the 0th element in the collection
Here are a few more but I'm not sure they would be very useful:
moveLast() - Sets current position to the last element in the collection
peekFirst() - Peek at the 0th element in the collection
peekLast() - Peek at the last element in the collection
To properly implement the functions listed above you should stay consistent and treat them almost like overloads. So, for example, internally peekNext() would actually just call peekAhead(1). This would keep your API's behavior consistent and simpler to maintain in case the implementation of the core function, peekAhead, needs to change.
And finally, here's the POJO. It just contains a single field, the token value, and a function to help write the value to console. Notice that the class does not have an index to itself because it isn't necessary.
// Your node/token class
public class Node {
private String token;
public Node(String token) {
this.token = token;
}
public String getToken() {
return token;
}
public void print() {
System.out.println(token);
}
}
For traversing forward and backwards you can use ListIterator instead of Iterator. You can get it from the LinkedList:
http://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html#listIterator(int)
I'm trying to learn linked-lists in Java and had some questions about the code below:
public class List {
Node root;
public List() {
// constructor
}
public int pop() {
// pop logic
}
public int push(int data) {
// push logic
}
}
I'd like to have a List class for popping and pushing data into the linked list. However, since the list won't have any default data on instantiation, what would be the best way for storing a reference to the root node?
In C, I would just have a pointer like:
Node * root;
But since Java does not have pointer, would having a simple declaration like:
Node root;
... be acceptable? I haven't used Java in a while, but doesn't allocating memory to an object declared as a class variable cause potential memory issues? Thanks!
Yes, a simple declaration like Node root is acceptable. It is not actually a pointer, but a reference that can potentially refer to any Node.
References in Java are conceptually equivalent to C pointers, but are less flexible and use a simpler syntax.
Yes,
Node root;
Is acceptable. Every non-primitive object (including arrays of primitives or objects) in Java is actually a reference to an object, so it is like a C pointer in many ways.
It is actually so much like a pointer, that this declaration by itself isn't actually creating an object. It is a reference that is not pointing to anything yet, and if you try to use root before assigning it to a new Node() first, you will get a NullPointerException.
Yes, Node root; is absolutely fine. Just make sure you don't change the value of root. For using it, create another variable, for traversing a path: Node start = root; This way root remains untouched.
I haven't used Java in a while, but doesn't allocating memory to an object declared as a class variable cause potential memory issues?
No it doesn't. While simply writing Node root; doesn't allocate any memory, root = new Node(); does. Take a note here that class members in java are static, the non-static members are global variables. Allocating memory to global variables in java is a common practice. For example, the variable where you actually store the list, will be a global variable, and you will have to allocate memory to it.
Java has a robust memory management system, so you won't run into memory issues too easily.