In Java (or any OOP language), I can make a nested class "Node", that represents some object that contains int data. I can then declare a "Node" reference with variable named "head":
public class ListNode {
class Node {
int value;
Node next = null;
public Node(int value) {
this.value=value;
}
}
Node head;
}
I can then do something like:
head = new Node(42);
...which should make the "head" reference point to a new Node object with int value 42, and a reference inside of it pointing to null:
But how can I actually make another reference that points to the "head" reference? I don't think its possible, but it would look like this:
I know that if I make another reference, like Node another_ref;
and then do another_ref = head
, all that will happen is another_ref
will point to whatever head was pointing to (Node that contains 42 in this case), so I will be left with 2 references pointing at a Node object with int value = 42, and Node next reference that points to null.
I know that I can take head.next
's reference, which is the Node object's reference pointing to null, and I can point it back at itself by doing head.next = head;
, but it doesn't seem like I can get anything to point back to the Node head
reference.
Am I missing something here? Can you not "chain" or "link" together references like this? Obviously I can create a bunch of new Nodes(integer values...)
with various integer values to chain-together a linked list, but just curious about this.
In C++, you can have pointers to pointers; you don't have that in Java. You can simulate it though:
Say you have the following Ref template interface:
public interface Ref<T> {
T get();
void set(T newValue);
}
Your Node
class could have a method that returns a reference to it's next
field:
public Ref<Node> getRefToNext() {
return new Ref<Node>(){
@Override
public Node get() {
return next;
}
@Override
public void set(Node newValue) {
next = newValue;
}
};
}
And class ListNode
could have a method that returns a reference to it's head
field:
public Ref<Node> getRefToHead() {
return new Ref<Node>(){
@Override
public Node get() {
return head;
}
@Override
public void set(Node newValue) {
head = newValue;
}
};
}
Now if you want to write a method that inserts a new node while keeping the list sorted, you can do:
public void insert(int value) {
Ref<Node> ref = getRefToHead();
Node node;
while ((node = ref.get()) != null && value < node.value) {
ref = node.getRefToNext();
}
Node newNode = new Node(value);
newNode.next = node;
ref.set(newNode);
}
But of course, it's much slower than with C++ pointers.
UPDATE
It allows you to reuse common code: Let's say you define a locate
method as follows:
private Ref<Node> locate(int value) {
Ref<Node> ref = getRefToHead();
Node node;
while ((node = ref.get()) != null && value < node.value) {
ref = node.getRefToNext();
}
return ref;
}
You can use it to find a node:
public Node find(int value) {
return locate(value).get();
}
And to insert a new node:
public void insert(int value) {
Ref<Node> ref = locate(value);
Node newNode = new Node(value);
newNode.next = ref.get();
ref.set(newNode);
}
The same principle can be used for binary trees.