Deep Copying in Java - java

I have a Java class, Node as follows :
class Node
{
public ArrayList<Node> nbrs;
}
Each Node object contains a list of all its neighbours within the ArrayList nbrs, and nothing else.
Now I need to write a function :
public Node copy( Node curr )
This function should perform a deep copy of the entire graph rooted at curr, and return the equivalent copy for curr.
I tried implementing a copy constructor within the class Node as follows :
public Node( Node n )
{
for( Node curr : n.nbrs )
n.nbrs.add( new Node( curr ));
}
I now copy the Node n, within my copy function.
But I have found that when the graph contains loops, this code keeps running infinitely.
Any help on how I should overcome this problem.
PS : This is an interview question faced by my friend, so the class Node cannot contain any more variables

If the Node class had a parent you'd be able to check for infinite recursion that way. But it doesn't. So you'll need to maintain some state during the clone operation, a Set containing the nodes you are currently recursing into. Refuse to descend into a node that is already in the Set.

Save the mapping between the old nodes being copied and the new ones in a data structure that allows retrieving elements based on identity (i.e. that retrieves objects iff the == operator returns true). An example for this would be the IdentityHashMap. If you create a new node, then save it to the data structure.
Before creating a new Node from a previous ony, try to retrieve the node from the data structure. If you have such a node already, then add the retrieved one to the parent. If you don't have such a node, then continue creating one (and add it).

The standard trick is to first create all the new nodes and store them in a map (from old nodes to new nodes). Then in a second pass over all the nodes, all the edges are added (by adding to n.nbrs.add).

Consider making Node objects immutable. In this case using shared instance will do no harm.

If you can modify the Node class and make it Serializable, then you serialize/deserialize the object and get a new graph of objects.
Sample code to illustrate the point:
class Node implements Serializable
{
public List<Node> nbrs = new ArrayList<Node>();
}
Node n1 = new Node();
Node n2 = new Node();
Node n3 = new Node();
n1.nbrs.add(n2);
n2.nbrs.add(n1);
n2.nbrs.add(n3);
n3.nbrs.add(n2);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream dos = new ObjectOutputStream(baos);
dos.writeObject(n1);
dos.writeObject(n2);
dos.writeObject(n3);
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bais);
Node n4 = (Node) ois.readObject();
Node n5 = (Node) ois.readObject();
Node n6 = (Node) ois.readObject();
At this stage, you'll have a new set of Node objects, which correctly reference each other.

There is no base case in the recursion, other than a node with no neighbors.
Daniel Earwicker suggested using a Set to make sure we don't add the same neighbor twice. Sounds good, but how can we tell if a node is in the Set? The default implementation of equals is really just == so no two nodes would be considered equal. The Set contains method relies on equals to determine if an object has already been added to a set. We cold add an id field to the node and then implement boolean equals(Node other) by checking for id equality. That should make the Set solution work.

Related

Create objects dynamically and run BFS

I want to modify the code below for getting data from file dynamically and run the BFS. I have tried with loop but i am stuck on how i will make dynamic connection of the nodes using the anonymous objects.
Node nA=new Node("101");
Node nB=new Node("102");
Node nC=new Node("103");
Node nD=new Node("104");
Node nE=new Node("105");
//Create the graph, add nodes, create edges between nodes
Graph g=new Graph();
g.addNode(nA);
g.addNode(nB);
g.addNode(nC);
g.addNode(nD);
g.addNode(nE);
g.setRootNode(nA);
g.connectNode(nA,nB);
g.connectNode(nA,nC);
g.connectNode(nA,nD);
g.connectNode(nD,nE);
There will be an edge file containing the connected nodes.My sample code is below
String[] nodes = {"1","2","3","4"};
ArrayList<Node> Nodelist = new ArrayList<Node>();
//create node objects
for(String val : nodes) {
Nodelist.add(new Node(val));
}
//create graph nodes from array nodelist
Graph g = new Graph();
for(Node val : Nodelist) {
g.addNode(val);
}
g.setRootNode(Nodelist.get(0));
//then in loop to create connection between nodes from file in structure [101,102] , [102,103] ...
for(){
int[] arr = file.split(",")
g.connectNode(arr[0],arr[1])
}
My problem here is with the object names.I have tried using anonymous object and then adding them in addNode() But how i will create the connection of the nodes that will be read from file using the anonymous objects array.I don't know if i am clear what i am trying to achieve.
How i can add them in HashMap but using same key and array of values.I have tried with arraylist but saves only the last value.
What you're missing is having a way to find a node by it's value. You can have it by replacing the list of nodes with a map, where node's value is a key (assumption: each value is different).
Map<String, Node> nodeMap = new HashMap<>();
for (String val: nodes) {
nodeMap.put(val, new Node(val));
}
Later on to connect nodes get them from nodeMap by their value.

Reversing a linked list in Java without changing the original

I am trying to reverse a linked list which works, but when I try to print the original, it fails (only prints the head). My question is, why would reversing affect the original. Below is my code. LinkedList is my own class, so is Node. Before reversing, if I try to print my list, that works.
public static void main(String[] args) {
LinkedList list;
...
Node head = list.getHead();
Node rev = reverse(head);
Node temp = rev;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
temp = head;
while (temp != null) {
System.out.println(temp);
temp = temp.next;
}
}
private static reverse(Node head) {
// Reversing the linked list
}
EDIT::
This seems to be a Java thing. Java passes an object by reference. When I pass head as a parameter, it's passed by reference and any change made to it is reflected in the calling function.
Doing Node h = head and then passing h as a parameter won't work either since h will be the same object as head.
The only option I can think of is to create a new object, copy the linked list over and pass that as a parameter.
My question becomes, is there a better solution?
To understand it, picture your list looks like this
list (list.head =a) --> a (a.next=b) --> b (b.next= c) -> c (c.next = null)
If you get the head, then you are getting object 'a'.
Then you are modifying object 'a'.
So you can see you are editing the list by doing this.
What you need to do is:
Get the head
Create a copy
Reverse the copy
Get the next item
Copy it
Reverse it
Join it to the last
And so on
Since you are using your own classes not java collections classes, the easiest way is for you to make sure that reverseNode() only edits a copy of the one you pass it, and returns the copy.
First make sure your Node class has a constructor that copies another Node, then do something like this:
private static Node reverse(Node original)
{
Node retval = new Node(original);
// or you could use clone () as Bhavik suggested, if your Node class implements it
// modify retval
// I haven't shown code to reverse it as I assume you already have that and you didnt specify if it was a bidirectional list or just one direction.
return retval;
}
Or you might add a static method in your Node class that constructs a new node that is reversed:
static Node createReverse(Node n)
{
return new Node(n.data,n.next,n.prior);
}
Or a non static method of the node class which returns a reversed copy of itself;
Node createReverse()
{
return new Node(this.data,this.next,this.prior);
}
But you should consider this can get very ugly because your copies will still have pointers pointing into the existing list!
A better technique might be to create a new empty list, and then start from the end of your original, make a copy, and add it to the start of your new list.
You can use recursion to do this but might easily run out of memory.
But rather than do this manually, you might look at the java.util packages and switch to using one of their LinkedList and list item types. These classes have already solved all the problems with doing this stuff.
Then you could (if you need to keep the original list unmodified):
- Make a copy of your entire list.
- reverse the copy as below
If you don't care about keeping the original, then just use this method(below) on your list, no need then to make a copy.
From java.util.Collections:
Collections.reverse(List a_list);
The Collections class will choose an efficient way to reverse the list, depending on whether it is bidirectional, single directional, etc.
Chunko's answer is right in that you should be creating copies of your Nodes instead of just passing references to them.
However, I think you might be overthinking this:
LinkedList reversedList = new LinkedList();
for (int i = originalList.size()-1; i >= 0; i--) {
reversedList.add(list.get(i));
}
Java's LinkedList doesn't have a getHead() method, so I guess you're using some homework-related custom implementation of a linked list. Still, your implementation should have an add() method that appends a new Node to the list, as well as a get(int) method that returns the item in a given position.
You can use those methods to create a new list and populate it with the original list's items in reversed order.

How a java class works with it's own reference type

I'm fairly new to JAVA and OOP and I'm currently following an academic course where I'm learning data structures and algorithms in java.
As I was learning about implementation of linked lists I've ran into a small problem of not understanding the code how to create a node when implementing a linked list(I'm familiar with constructors and bit of recursion ).
Code of the Node class as follows
public class Node {
public int info;
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
public Node (int el,Node n,Node p){
info = el; next =n; prev=p;
}
}
I need to know what's happening behind the scene when the code executes(especially how the line3 works)and code of the List class is as follows
public class List {
private Node head, tail;
public List ( ){
head = tail = null;
}
public boolean isEmpty( ){
return head == null;
}
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
public int removeFromTail ( ){
int el = tail.info;
if (head == tail)
head = tail =null;
else
{
tail = tail.prev; tail.next = null;
}
return el;
}
}
(This example is given by the academy where I'm learning and I want to know how it works)
Please explain how the Node class works.
Ok let's start from the Node Class
public Node next, prev;
public Node (int el) {
this (el,null,null);
}
Here the objects next and prev are references to the next and previous nodes to the current node (which is your current object (this))
this (el,null,null);
It means you are creating a node which has no previous or next node. as you pass null, null for next and previous. Its similar to creating a head as head doesn't have next and previous nodes.
When you create the head you will never change it but you will change the next of the head the time when you create the second element in your list
When you create a tail of the linked list
public void addToTail (int el) {
if (!isEmpty ( )) {
tail = new Node (el, null, tail);
tail.prev.next = tail;
}
else head = tail = new Node(el);
}
here you first create a tail Node by tail = new Node (el, null, tail);
And then get the previous of tail and set the next element of the prev as the tail by doing tail.prev.next = tail;
Every time you add a new Node to the list you are calling addToTail(int e1) which updates the tail and updates the next of the old tail.
Let's suppose the entry point of your code is a call to:
List list = new List();
list.addToTail(1);
list.addToTail(2);
list.removeFromTail();
The first line of code execute the constructor into the list class, which simply set head and tail equal to null.
The second line of code add the method addToTail, and set the variable head and tail equal to new Node(1), which invoke the constructor having one parameter only in the Node class.
The third line of code add the method addToTail, but this time the list is not empty, so the script enters in the if statement and the node that you save with Node(2, null, tail). If you check this Node constructor with three parameters, tail (the node you added before which value was 1) will be set as the prev (previous) node associated with the current one.
The last line of code remove the 2nd node with the code tail = tail.prev; tail.next = null; and return the element you just removed.
firstly node in java its a specific type of variable, which can do the normal work of a variable and have an other information allow her to point on an other node in your case is public Node next, prev;
usually node are used in list ,think like train this is why you have addtootail here or removefromtail .
in this link you find a pretty quite explanation about that.
http://www.vias.org/javacourse/chap14_02.html
The Node class encapsulates the data, in this case an integer value named info.
Also, the List is implemented as a sequence of Nodes.
The reason for the next and prev values in Node is so that the node can be linked to its previous and next nodes in the list sequence. The only way to access a node in the list is to traverse the list, either forwards using the next reference, or backwards using the prev reference.
Note that lists do not support random access like an array would. To get to an element, you need to traverse the list in some direction.
I need to know what's happening behind the scene when the code executes(especially how the line3 works).
Please explain how the Node class works.
public Node next, prev;
Java variables that refer to object types are references, not values. The fields next and prev are not Node objects. No Node object contains other Nodes. Instead, next and prev reference Node objects stored separately.
If you're coming from C or C++, you can think of these references somewhat like pointers.
EDIT:
If you're instead asking about the construction of linked lists in general, your Node class represents a single node, containing a single item, in a doubly linked list. In a doubly linked list, each node refers to the node before and the node after.
See this illustration of a doubly linked list in this related wikipedia article.
The List is like a train. A Node is like a car in the train. The links are references between Nodes, which are similar to the coupling between train cars. The next and prev fields that you ask about are the links between nodes.
Logically, the List contains the entire train. Physically, your List references the head and tail of the train, so that it can travel over the Nodes from front-to-back, or back-to-front.

The "header" in the LinkedList class in Java API

In reading the LinkedList doc, I am a little puzzled by the uses of "header". Normally, the header is the first node in a linkedList. But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list, thus making the LinkedList a circular one. Is that true?
private transient Entry<E> header = new Entry<E>(null, null, null);
public LinkedList() {
header.next = header.previous = header;
}
public E getFirst() {
if (size==0)
throw new NoSuchElementException();
return header.next.element;
}
public E getLast() {
if (size==0)
throw new NoSuchElementException();
return header.previous.element;
}
public E removeFirst() {
return remove(header.next);
}
But here it looks like the 'header' is a dummy node in the list and it points to the first and last nodes of the list
That much is true
thus making the LinkedList a circular one.
That's not exactly true: structurally, the list is indeed circular, because the header "loops" it around. That is only an implementation detail, a common trick that lets you avoid declaring two things (header and tailPiece) instead of one. The fact that the same entry is used for both ends by itself is insufficient to make the list circular: there is no way for you to loop around the last node "from the outside", because the count prevents you from doing so.
You're right. header stores references to both the head and tail of the list. This helps in reducing cost of operations involving delete/add/view for both the ends of the list.
With the availability of references to both the ends, operations like getFirst, getLast, removeFirst, removeLast, addFirst, addLast etc. don't require list traversal.
A circular list is a cheap way to avoid storing both head and tail pointers in the top-level structure. I don't know about Java's LinkedList implementation, but this is certainly a trick pulled in e.g. the GCC implementation of std::list.
The implementation of LinkedList is using what's called s sentinel node. They've chosen to use one sentinel for both head and tail; other implmentations will use two separate sentinels.
In either case, the use of sentinels allow the rest of the implementation code to not deal with the null case. For example, consider adding a node. Without a sentinel:
Node newNode = ...;
if (header == null) {
header = newNode;
tail = newNode;
} else {
newNode.previous = tail;
tail.next = newNode;
tail = newNode;
}
With the sentinel:
Node newNode = ...;
newNode.previous = sentinel.previous;
newNode.next = sentinel;
sentinel.previous = newNode;
Here's the Wikipedia article on Sentinel Nodes.

How do I insert a new node before first node of a doubly-linked list?

I am looking at how to insert a new node before the first node of a doubly-linked list. I'm getting confused with the auxiliary nodes required for this operation and the sequence of steps in which to perform the operation. I would be grateful for a hint on how to solve this problem i.e. what is wrong with my insertBeforeFirst method. As it stands the method causes a nullPointerException which i find hard to troubleshoot. (note: this is a follow-on to a previous post.)
public DLL()
{
header = null ;
tail = null ;
}
...
DLL myList = new DLL() ;
DLLNode A = new DLLNode("Hello", null, null) ;
DLLNode B = new DLLNode("Hi", null, null) ;
...
myList.addFirst(A) ;
myList.insertBeforeFirst(B)
...
public void addFirst(DLLNode v)
{
v.pred = header ;
v.succ = tail ;
header = v ;
tail = v ;
}
...
public void insertBeforeFirst(DLLNode v)
{
DLLNode aux = v ;
aux.succ = header.succ ;
header = aux ;
DLLNode aux2 = aux.succ ;
aux2.pred = v ;
}
[EDIT]
I've followed Aaron's advice and made a drawing and i have a slight improvement in that i don't get a nullPointerException anymore but the new mode is inserted after the first node rather than before. So my drawing skills need some polishing too i think :)
public void insertBeforeFirst(DLLNode v)
{
v.succ = header.succ ; // point new node succ to current first node
header.succ = v ; //point header to new node
DLLNode aux = header.succ ; // auxiliary node for backward insertion
aux.pred = v ; // point auxiliary's pred backward to new node
}
[EDIT2]
Looking at the post by MahlerFive I see now why some of you might get confused by my header and tail talk. Here is where i got it from: "To simplify programming, it is convenient to add special nodes at both ends of a doubly linked list: a header node just before the head of the list, and a trailer node just after the tail of the list. These "dummy" nodes do not store any elements" source
So it seems that for a starter i need to find a way to implement these dummy nodes correctly before i can add anything and make correct references. these DUMMY nodes seem to require a different Node constructor? Could they be instantiated by the DLL default constructor?
[EDIT3]
#MahlerFive, the DLL constructor will look like this:
public DLL()
{
DLLNode Header = new DLLNode(null, null, null) ;
DLLNode Tail = new DLLNode(null, Header, null) ;
Header.succ = Tail ;
}
and my method something like this, although i'm getting a nullPointerException at the moment:
// insert z before v
public void addBeforeFirst(DLLNode v, DLLNode z)
{
DLLNode aux = v.pred ;
z.pred = aux ;
z.succ = v ;
v.pred = z ;
aux.succ = z ;
}
[EDIT4]
I'm making progress. (great feeling!) I am in agreement with MahlerFive that the DUMMY Header and Tail nodes are not a great way to approach this. But as it was mentioned in a published book on the matter it was worth at least exploring. Here goes my new code (without the use of dummy nodes):
...
// DLL Constructor
public DLL()
{
first = null ;
last = null ;
}
...
// example insert call
// B is the node in front of which i want to insert
l.insert("Ciao", B) ;
...
public void insert(String elem, DLLNode pred)
{
// make ins a link to a newly-created node with element elem,
// predecessor null, and successor null.
DLLNode ins = new DLLNode(elem, null, null) ;
// Insert ins at the insertion point in the
// forward SLL headed by first.
ins.pred = first ;
ins.succ = first ;
// let first be the the new node
first = ins ;
}
this needs fine tuning as i haven't set any backwards links yet but it's a great starting point. To make sure this works correctly (at least in the forward way) i added print statements to print out the first and last element as i added nodes. Indeed they were updated correctly:
Hi
first: hi
last: hi
Ciao Hi
first: Ciao
last: hi
Moin Ciao Hi
first: Moin
last: hi
Instead of doing this all in your brain, sit down five minutes and draw the data structure (DLL and 2-3 couple of nodes) on paper.
Leave a gap and below that, draw how it would look with the node already inserted.
Mark all the changes you need to make with a marker pen. Give each change a number.
Now sit down and implement each change.
This sounds tedious but it will help you deeply understand what is going on. This way, you will have to do this only once.
If you're more the paper and scissors type, get pieces of string, cut out the nodes and glue post it notes to the end of the strings. Now you can use the strings as "references" between elements of your model.
It looks like most of your confusion is around how header works. It is just a reference to the first node in the list. Also, there is no need for an "auxiliary" node.
Lets look at the steps you need to take in order:
Step 1: Set the pred of the node you are inserting.
Since the node will become the first node, it will have no nodes behind it, so you can say v.pred = null;
Step 2: Set the succ of the node you are inserting.
Our new node needs to point forward to the old first node. Here's where the confusion comes. You do the following:
v.succ = header.succ ; // point new node succ to current first node
But what is header? It is a reference to the first node. By saying header.succ you are saying you want the first nodes successor, which is the second node. When you see header just think "first node" and you will come up with:
v.succ = header;
Step 3: Point the old first node back to the new node
You already are doing this step correctly (remember, think header is "first node"):
header.succ = v ; //point header to new node
Step 4: Now make the new node the header
header = v;
EDIT (in response to your edit #3):
There are some issues about this whole approach which I'll bring up at the end, but those aside for now and assuming you are required to set up your list this way...
Assuming you're passing in the first node of the list (Header.succ) as v, let's take the same steps:
Step 1: Set the pred of the node you are inserting.
You want your new node to point back toward Header.
v.pred = Header;
Step 2: Set the succ of the node you are inserting.
You want your new node to point to the old first node, which was Header.succ
v.succ = Header.succ;
Step 3: Point the old first node back to the new node
Make sure you check that a first node exists first (forgot this in my first post)!
if (Header.succ != null) {
Header.succ.pred = v; // Header.succ is the first node, and you want to set its pred reference
}
Step 4: Now make the new node the first node
Header.succ = v;
Note how you don't even need z since you can get to the first node using Header.succ. This means you shouldn't need it as a parameter.
Now, all that aside there are some issues you should think about:
What is the point of a Header having a pred reference and a data field? What is the point of a Tail having a succ reference and a data field?
If you wanted to use this linked list and insert items, wouldn't it be better if you just had to call add() for every item instead of addFirst() and addBeforeFirst()? What if you could a remove() method, then you'd have to keep track of if the list is empty or not to figure out which method to call, addFirst() or addBeforeFirst(), which is kind of ugly. It's better to write a more generalized add() which takes care of this for the user who is going to use the list.

Categories

Resources