Java: Pass by reference for mutable objects in recursion - java

In java I know that references are also passed by value. Is the only way to get this working is by returning prev? Are there other alternatives?
head is class variable
convertTreeToSortedDoublyLinkedList(root, null);
private void convertTreeToSortedDoublyLinkedList(Node node, Node prev) {
if(node == null){
return;
}
convertTreeToSortedDoublyLinkedList(node.left, prev);
node.left = prev;
if(prev != null) {
prev.right = node;
} else {
head = node;
}
Node right = node.right;
head.left = node;
node.right = head;
prev = node;
convertTreeToSortedDoublyLinkedList(right, prev);
}

Another option is to have an object with the references to node and priv inside it, modify that object from the called method and the calling method will see the change.

There are two options:
You return the new reference as you suggested
You wrap the reference in another reference so you can update the inner reference without a problem.
A simple solution would be an array:
Node[] ref = new Node[1] {prev};
ref[0] = //update here
I think option one would be better here because the Ref-Ref or the array would just clutter the method

Related

Storing One String Value in an empty LinkedList

public class LinkedListExplained {
public Node head;
public Node tail;
public int size;
public LinkedListExplained() { // Constructor
head = null;
tail = null;
size = 0;
}
public class Node{ // Inner Class
String value;
Node next;
}
public void add(String value){
Node node = new Node();
node.value = value;
size++;
if (head == null){
head = node;
tail = node;
return;
}
tail.next = node;
tail = node;
}
Question, when storing a single String value to an empty LinkedList, does it store the same value twice?
Once as head and once as tail?
No. The head and tail variables point to the same Node object. That object contains the String once.
If you are learning Java, the first and foremost thing you need to understand is that in Java, everything that looks like an object is never actually an object; it is a pointer to an object. And of course two pointers may point to the same object.
So, the statement public Node head; does not declare an instance of Node. It declares a pointer to an instance of Node. That's why you have to use new Node(); later.
So, since you set both the head and the tail pointers to point to the same instance of Node, it might appear that you have two copies of that node, but in fact you do not. You only have one instance of Node, and you have two pointers pointing at it.

Removing Duplicates from sorted LinkedList Relation b/w "slow" and "head"

Can someone please explain how it is getting the correct output when we are not updating the "head"?
public ListNode deleteDuplicates(ListNode head) {
ListNode slow = head;
while (slow.next != null) {
if (slow.val == slow.next.val) {
slow.next = slow.next.next;
}
else {
slow = slow.next;
}
}
return head;
Here the ListNode object reference is passed as a value to deleteDuplicates and the same reference is assigned from head to slow (slow = head;), so after this method is returned your ListNode object will hold the change
for more clarification please check this
Thank you.

How to "delete" a node from a binary search tree in Java?

I made a binary search tree in Java but I'm having troubles whit the deleting nodes part. I managed to erase the node when it has only 1 son, and I have the idea to make the deletion when it has 2 sons, anyways the method I'm using when it has no sons (when it's a leaf) is not working in Java. Normally in C++ I would assign the Node "null" but it doesn't work here.
if (numberOfSons(node) == 0) {
node= null;
return true;
}
That's the portion of the code that takes care of the nulling part. When I debug it, it is referencing the correct node and it's assigning it the null value, but when I return to the Frame where I'm calling the delete method for my tree the node is still there. What's the correct way to "null" an object in Java? I thought everything was a pointer in here and therefore this would work, but I think it doesn't.
When you're nulling something you just make the reference in the scope you're in null. It doesn't affect anything outside.
Let me explain by example. Say you have a method foo:
public void foo(Node node) {
node = null;
if(node == null) {
System.out.println("node is null");
} else {
System.out.println("node is not null");
}
}
Now you call it like this:
public void doSomething() {
Node node = new Node();
foo(node);
if(node == null) {
System.out.println("Original node is null");
} else {
System.out.println("Original node is not null");
}
}
In your console you'll get:
node is null
original node in not null
The reason is that it's not a pointer, it's a reference. When you're nulling a reference, you just say "make this reference synonym to null". It doesn't mean that the object is deleted, it may still exist in other places. There is no way to delete objects in java. All you can do is make sure no other object points to them, and the garbage collector will delete the objects (sometime).
Nothing remains but to reinsert either left or right subtree. For instance:
class BinaryTree<T extends Comparable<T>> {
class Node {
Node left;
Node right;
T value;
}
Node root;
void delete(T soughtValue) {
root = deleteRec(root, soughtValue);
}
Node deleteRec(Node node, T soughtValue) {
if (node == null) {
return null;
}
int comparison = soughtValue.compareTo(node.value);
if (comparison < 0) {
node.left = deleteRec(node.left, soughtValue);
} else if (comparison > 0) {
node.right = deleteRec(node.right, soughtValue);
} else {
if (node.left == null) {
return node.right;
} else if (node.right == null) {
return node.left;
} else {
// Two subtrees remain, do for instance:
// Return left, with its greatest element getting
// the right subtree.
Node leftsRightmost = node.left;
while (leftsRightmost.right != null) {
leftsRightmost = leftsRightmost.right;
}
leftsRightmost.right = node.right;
return node.left;
}
}
return node;
}
}
As Java does not have aliases parameters as in C++ Node*& - a kind of in-out parameter, I use the result of deleteRec here. In java any function argument that is an object variable will never change the variable with another object instance. That was one of the language design decisions like single inheritance.

How to reuse the code in situations where input param is a reference ?

This code would convert a linkedlist like : 1-> 2 -> 3 -> 4, into 1->3-2->4 (ie odd on left and even on right), except the problem caused by oddEvenSplitter function. This code will modify references by value. How to reuse the code in such situations where input is a reference ?
public void oddEvenSplitter (Node head, Node current, Node temp) {
if (head == null) {
head = temp;
current = temp;
} else {
current.next = temp;
current = temp;
}
}
public void oddFirst( ) {
if (first == null) {
throw new NoSuchElementException();
}
Node temp = first;
Node oddhead = null;
Node odd = null;
Node evenhead = null;
Node even = null;
while (temp != null) {
if (temp.element % 2 == 0) {
oddEvenSplitter(evenhead, even, temp);
} else {
oddEvenSplitter(oddhead, odd, temp);
}
}
if (oddhead != null) {
odd.next = evenhead;
first = oddhead;
}
}
Java does not have pass by reference. It always passes values. When you pass for example oddHead variable to oddEvenSplitter() method, what really happens is that a copy of oddHead variable is passed and from that point head and oddHead variables will be two separate variables, pointing on same object in the heap. So if you assign new value to head variable inside your method, the other one (oddHead) will remain unchanged. This is true for all other passed parameters as well.
As a solution you could create another object (like a DTO) and put all needed references inside it and pass it to your method. Then whenever you change those references, you will be able to get them in caller method.

How to deep copy a Binary Tree?

I would like using my own Node class to implement tree structure in Java. But I'm confused how to do a deep copy to copy a tree.
My Node class would be like this:
public class Node{
private String value;
private Node leftChild;
private Node rightChild;
....
I'm new to recursion, so is there any code I can study? Thank you!
try
class Node {
private String value;
private Node left;
private Node right;
public Node(String value, Node left, Node right) {
this.value = value;
...
}
Node copy() {
Node left = null;
Node right = null;
if (this.left != null) {
left = this.left.copy();
}
if (this.right != null) {
right = this.right.copy();
}
return new Node(value, left, right);
}
}
Doing it recursively using pre-order traversal.
public static Node CopyTheTree(Node root)
{
if (root == null)
{
return null;
}
Node newNode = new Node(null, null, root.Value);
newNode.Left= CopyTheTree(root.Left);
newNode.Right= CopyTheTree(root.Right);
return newNode;
}
You can use something like this. It will go though the old tree depth first wise and create a copy of it.
private Tree getCopyOfTree(oldTree) {
Tree newTree = new Tree();
newTree.setRootNode(new Node());
copy(oldTree.getRootNode(), newTree.getRootNode())
return newTree;
}
private void copy(Node oldNode, Node newNode) {
if (oldNode.getLeftChild != null) {
newNode.setLeftChild(new Node(oldNode.getLeftChild()));
copy(oldNode.getLeftChild, newNode.getLeftChild());
}
if (oldNode.getRightChild != null) {
newNode.setRightChild(new Node(oldNode.getRightChild()));
copy(oldNode.getRightChild, newNode.getRightChild());
}
}
I like Evgeniy Dorofeev's answer above, but sometimes you might not be able to add a method to the type Node as you might not own it. In that case(this is in c#):
public static TreeNode CopyTree(TreeNode originalTreeNode)
{
if (originalTreeNode == null)
{
return null;
}
// copy current node's data
var copiedNode = new TreeNode(originalTreeNode.Data);
// copy current node's children
foreach (var childNode in originalTreeNode.Children)
{
copiedNode.Children.Add(CopyTree(childNode));
}
return copiedNode;
}
Not sure but try something with post order traversal of your tree and creating a new node for each node you traverse. You might require stack for storing the nodes you created to make left and right child links.
public static TreeNode copy( TreeNode source )
{
if( source == null )
return null;
else
return new TreeNode( source.getInfo( ), copy( source.getLeft( ) ), copy( source.getRight( ) ) );
}
/Sure. Sorry for the delay. Anyway... any recursive method has a base case, and one or more recursive cases. In this instance, the first line is obvious... if the argument to the parameter 'source' is null (as it eventually evaluates to in order to end the method's operation), it will return null; if not, the recursive case is initiated. In this case, you're returning the entire copied tree once the recursion is complete.
The 'new' operator is used, indicating the instantiation of a TreeNode with each visit to the various nodes of the tree during the traversal, occurring through recursive calls to 'copy', whose arguments become references to the left and right TreeNodes (if there are any). Once source becomes null in each argument, the base case is initiated, releasing the recursion stack back to the original call to 'copy', which is a copy of the root of the original tree./
Node copy(Node node)
{
if(node==null) return node;
Node node1 =new Node(node.data);
node1.left=copy(node.left);
node1.right=copy(node.right);
return node1;
}

Categories

Resources