I have a class that looks something like this:
public class Node {
private final Node otherNode;
public Node(Node otherNode) {
this.otherNode = otherNode;
}
}
and want to do something like
Node n1, n2 ;
n1 = new Node(n2);
n2 = new Node(n1);
but obviously cannot since n2 is not initialized yet. I don't want to use a setter to set otherNode because it's final, and thus should only be set once ever. What is the cleanest approach to accomplishing this? Is there some fancy Java syntax I'm unfamiliar with to let me do this? Should I use an initialize method in addition to the constructor (ugly), or just cave and use a setter (also ugly)?
Have a second constructor that takes no parameters and constructs its own Node, passing itself as the other's "other".
public class Node
{
private final Node otherNode;
public Node(Node other)
{
otherNode = other;
}
public Node()
{
otherNode = new Node(this);
}
public Node getOther()
{
return otherNode;
}
}
Then when using it:
Node n1 = new Node();
Node n2 = n1.getOther();
Assuring that they refer to each other:
System.out.println(n1 == n1.getOther().getOther());
System.out.println(n2 == n2.getOther().getOther());
System.out.println(n1 == n2.getOther());
System.out.println(n2 == n1.getOther());
These all print true.
(This is a supplement to rgettman's answer.)
A more general solution is to write a constructor like:
private Node(final int numNodesInLoop) {
if(numNodesInLoop < 1) {
throw new IllegalArgumentException();
}
Node head = this;
for(int i = 1; i < numNodesInLoop) {
head = new Node(head);
}
this.otherNode = head;
}
Your case, with two nodes, would be instantiated as new Node(2).
I made the above private, per a comment by user949300 to rgettman's answer, because the meaning of a Node constructor that takes an int is not very guessable (it creates a loop?!), so it's better to wrap it in a static factory method whose name makes its functionality clear:
public static Node newNodeLoop(final int numNodes) {
return new Node(numNodes);
}
(This is also more future-proof in case you later have a need for another constructor that would take an int, for whatever reason. You can then modify this constructor to take a dummy argument as well, just enough to tell the compiler what constructor you want. The factory method would still have the same contract.)
Related
I am unfamiliar with generics, so in this method here where i'm trying to implement a remove method from scratch, :
public class LinkedList<T> implements LinkedListInterface<T> {
private Node head;
private Node tail;
private int count;
public LinkedList () {
head = null;
tail = null;
count = 0;
}
class Node {
T data;
Node next;
Node(T data) {
this.data = data;
next = null;
}
}
public Node getHead() {
return head;
}
public T remove(int pos) throws ListException {
if (pos < 1 || pos > count) {
throw new ListException("Invalid position to remove from");
}
Node removedItem = null;
if (count == 1) {
removedItem = head;
head = null;
tail = null;
}
else if (pos == 1) {
removedItem = head;
head = head.next;
}
else if (pos == count) {
removedItem = tail;
Node prev = jump(pos - 2);
prev.next = null;
tail = prev;
}
else {
Node prev = jump(pos - 2);
removedItem = prev.next;
prev.next = prev.next.next;
}
count--;
return removedItem; // error: incompatible types: LinkedList<T>.Node cannot be converted to T
}
}
I need help identifying what this 'T' is exactly in the remove method and what this error message means and what I should do to fix it, thanks for the help
Generics (or rather, the proper name, 'type variables') is a way to link things.
All Ts represent a type. Everyplace T is mentioned, it's the same type for any given 'usage' of a thing, but you don't know what T is. It could be Number, it could String, it could SomethingYouNeverHeardAbout. But it's some type or other. If you did know, you'd just write that out instead.
In your snippet, public LinkedList<T> declares the type variable (just like you need to type int x; before you can start using x as a variable that can hold values, you need to declare a type variable, and that's where it is declared. T has no restrictions - it can be any type (except primitives, because primitive types and generics don't mix at all, at least, for now - maybe future java versions change this).
All other occurrences of T in the entire file are simply usages of it.
In other words, your code says: For any specific LinkedList, it has some type associated with it. We have no idea what it is, but every instance has such a thing.
Generics are entirely a compile time affair so this has no effect whatsoever when you run the code, it's solely for the compiler to help you out and tie things together. The point of the exercise is simply to let you tell the compiler that various types used in different places are unknown, but we do know, they are the same.
So, given any particular instance of LinkedList, its remove method returns the same type that its add method receives. Which is the same type as the data field of its internal Node inner class.
What does this get you? Compile-time checking, for one. The compiler can now find bugs for you. And so it has! Your intent is clearly for the remove method to return the thing it removed, but you aren't doing that. You are actually returning the node object that contains the thing you removed. This node object isn't even publicly visible (your Node internal class has package private access), clearly completely useless to return that, and as per your signature, you didn't mean to.
To fix your bug, just write return removedItem.data; instead.
In one algorithm question "Implement Queue by Linked List", the solution shows create the class Node first:
class Node {
public int val;
public Node next;
public Node(int _val) {
val = _val;
next = null;
}
}
May I ask the meaning of the leading underline of val = _val?
_val is just a name. This code is exactly equivalent in every way to
public Node(int iJustMadeUpAVariableName) {
val = iJustMadeUpAVariableName;
next = null;
}
and it initializes the val field in the Node class to the value passed into the constructor.
I have a home work in a data structures course, the question is:
Implementation of doubly-linked list class.
the methods:
display()
length() or size()
insertSorted(Comparable)
insertToEnd(Comparable)
insertToHead(Comparable)
delete(Comparable)
boolean search(Comparable)
You must do this in JAVA
Create an application layer to test your class and its methods.
Compress all of your source files into a file and rename it as CS214HW1_first_lastName.zip Put your name in the filename. If needed, add a ReadMe.txt file for extra information such as compilation.
I implemented everything correctly and the code is working fine, but I used for example: insertSorted(int) instead of insertSorted(Comparable), because I didn't know how to do it.
I searched online, and read the JAVA documentation for (Comparable) but it is not enough :(
Can anybody help, please it is very important?
Here's some of my code, I can't write it all, cuz I don't want my friends to get the same code.
I will take zero if there is same code.
Code:
class DLL {
class Node {
Node next;
Node prev;
int data;
Node() {
next = null;
prev = null;
data = 0;
}
Node(int dt) {
next = null;
prev = null;
data = dt;
}
}
Node head;
void insertToHead(int dt) {
if (head == null) {
head = new Node(dt);
}
else {
head.prev = new Node(dt);
head.prev.next = head;
head = head.prev;
}
}
public static void main(String args[]) {
DLL dll = new DLL();
dll.insertToHead(1);
dll.insertToHead(2);
dll.insertToHead(3);
}
}
Please, somebody, tell me what to change in the beginning of the class.
are we gone use extends or implements Comparable<E> or what!
and what changes should i do the method insertToHead(Comparable)
what changes should i do to the main.
You would probably like to look into how generics work as well. The basic idea is that you would like to set up your class so that it will not know exactly the specific type of object but can be given some hint at the types of things it can expect of a declared generic type.
In your case, you would like to set up your list so that you can create linked lists of anything that can be compared. Java has a class for that which you have mention called Comparable<E> this tells Java that it will be able to call such methods as compareTo on the provided object.
More specifically to your closing questions:
Use the following style of class declaration MyClass<MyGenericType extends Comparable<MyGenericType>>. In your case DLL<E extends Comparable<E>>.
Switch the method arguments to accept E our declared generic type.
You should use the class Integer instead of the primitive type int, and change the creation of your list to DLL<Integer> dll = new DLL<Integer>().
Fully updated version of provided code:
public class DLL<E extends Comparable<E>> {
class Node {
Node next;
Node prev;
E data;
Node() {
next = null;
prev = null;
data = null;
}
Node(E dt) {
next = null;
prev = null;
data = dt;
}
}
Node head;
void insertToHead(E dt) {
if (head == null) {
head = new Node(dt);
}
else {
head.prev = new Node(dt);
head.prev.next = head;
head = head.prev;
}
}
public static void main(String args[]) {
DLL<Integer> dll = new DLL<Integer>();
dll.insertToHead(1);
dll.insertToHead(2);
dll.insertToHead(3);
}
}
This new implementation should provide a hint for how to proceed with some of the other homework tasks. For instance you can now compare objects just by their compareTo method which might useful for sorting hint hint.
That doc page gives a very good explanation for how to use this method. You should note that in their docs, they use a generic type called T instead of E, it really doesnt make a difference you can call it whatever you want provided it is unique to your program.
Edit:
An each hint in the sorting direction:
Ojbects which extend the Comparable class have a method which is called compareTo this method is set up so you can call:
object1.compareTo(object2);
this method returns an int which will be:
> 0 when object1 is greater than object2
= 0 when object1 is equal to object2
< 0 when object1 is less than object2
I don't want to give away too much as this is a homework assignment but here is my hint:
The way the above code sets up your classes, you would be able to tell the relationship between NodeA and NodeB by calling:
NodeA.data.compareTo(NodeB.data)
this will return an integer which gives your information according to the list above.
The <=,>=,== operators are likely found in the Integer class's compareTo method.
Something like:
public int compareTo(Object o) {
int otherNumber = ((Integer) o).intValue();
int thisNumber = this.intValue();
if (otherNumber > thisNumber) {
return 1;
} else if (otherNumber < thisNumber) {
return -1;
} else {
return 0;
}
}
but more likely they just do something like:
public int compareTo(Object o) {
return this.intValue() - o.intValue(); // possibly normalized to 1, -1, 0
}
See the Docs on Integer for more info on this.
Java is pass by value. What if I need a pass by reference. For example in the following code I need a pass by reference mechanism.
public class BinaryTree {
public TreeNode root;
public BinaryTree(){
root = null;
}
public TreeNode insert(TreeNode temp,int x){
if(temp == null){
temp = new TreeNode();
temp.key = x;
temp.left = temp.right = null;
return temp;
}
if(temp.key > x)
temp.left = insert(temp.left,x);
else if(temp.key < x)
temp.right = insert(temp.right,x);
return null;
}
}
When insert is called with root, I need root to be passed as a reference so as to change its value. But this does not happen in Java, since it's pass by value. In C/C++ the above could be easily achieved. Don't you think that this is a drawback of Java? How could such problems be solved in Java?
In Java, if you have a reference type the reference is passed by value.
Inside the method you can mutate the object that was passed and the caller will see those changes.
Don't you think that this is a drawback of Java?
No. Because:
There are few cases where you really need it.
There are workarounds (see below).
Implementing pass by reference in Java would be difficult. It makes code generation and garbage collection significantly more complicated.
(OK ... so really these are counter-arguments. But we are talking about a language design issue here, and any rational discussion of language designs has to weigh up the pros and cons of supporting a particular feature. And that includes implementation cost and performance issues.)
How could such problems be solved in Java?
The general approach is to restructure your code so that the variable you need to update in the called method is replaced with a reference to a mutable object or an array. This may entail the caller doing a bit more work, but that is generally acceptable.
Alternatively (and in your example) restructure the code so that call by reference is unnecessary.
In your example, there are two observations to make:
The "call-by-reference" mechanism is only used in the case where the tree is empty. It is not difficult to change this so that it is not necessary.
In fact, your use of call-by-reference, and in fact the entire insert method, is a leaky abstraction. There is nothing to stop you calling the method with a node object that is nothing to do with the current BinaryTree instance. You are relying on the caller to maintain the (implied) invariants of the tree.
The following version addresses both of these issues:
public class BinaryTree {
private static class TreeNode { ... }
public TreeNode root;
public BinaryTree(){
root = null;
}
public void insert(int x) {
root = insert(root, x);
}
private TreeNode insert (TreeNode node, int x) {
if (node == null) {
return new TreeNode(x);
}
if (node.key > x)
node.left = insert(node.left, x);
else if (node.key < x)
node.right = insert(node.right, x);
return node;
}
}
(I don't exactly like the way that we reassign the left / right pointers at each level after the insertion, but it does make the insertion logic simple.)
root can be changed by getting the return value.
public void insert(int x) {
root = insert(root, x);
}
I changed the method insert(...) a little.
private TreeNode insert(TreeNode temp,int x){
if(temp == null){
temp = new TreeNode();
temp.key = x;
temp.left = temp.right = null;
}
if(temp.key > x)
temp.left = insert(temp.left,x);
else if(temp.key < x)
temp.right = insert(temp.right,x);
return temp;
}
Java is pass by value for everything. Whether you are working with primitives or with reference types.
The "value" or a reference type is the reference itself, so when using reference types the reference itself is passed.
I have 2 questions about linked lists so i figured i'll post them in one question.
first i'll show my node class and the copy constructor and constructor from a string
class CharNode
{
private char letter;
private CharNode next;
public CharNode(char ch, CharNode link)
{
letter = ch;
next = link;
}
public void setCharacter(char ch)
{
letter = ch;
}
public char getCharacter()
{
return letter;
}
public void setNext(CharNode next)
{
this.next = next;
}
public CharNode getNext()
{
return next;
}
}
copy constructor
// copy constructor
public CharList(CharList l)
{
CharNode pt = head;
while(pt.getNext() != null)
{
this.setCharacter() = l.getCharacter();
this.setNext() = l.getNext();
}
}
constructor from string
// constructor from a String
public CharList(String s)
{
head = head.setCharacter(s);
}
when i try to compile i get an error for my copy constructor it says that it cant find the symbol this.setCharacter()... and the l.setCharacter()...
am i just doing it completely wrong?
and with my constructor from a string i know thats wrong. i thought about using the charAt() but how would i know when to stop the loop to do that? is that a good approach to take?
any help would be appreciated.
in your CharList constructor, this refers to the CharList class, which doesn't have a setCharacter() method (CharNode does). also, when you call a method in java, you need to pass the parameter, e.g. setFoo(newFoo), not setFoo() = newFoo
Your set character method is probably in your node, not in your list. You also need to be moving your pointer along. What I mean is, where do you ever "go to the next node"?
Your copy constructor is for the class CharList, while setCharacter is defined in CharNode.
this in the copy constructor references the current instance of the CharList object the constructor is defined on. l is also a CharList in your code rather than a CharNode which defines setCharacter.
The copy constructor should be defined in the CharNode class.
In your "copy constructor" you would need to go through the list being passed in starting with its head, and create new nodes for your new list ...
public CharList(CharList l)
{
// Whatever method your CharList provides to get the
// first node in the list goes here
CharNode pt = l.head();
// create a new head node for *this* list
CharNode newNode = new CharNode();
this.head = newNode;
// Go through old list, copy data, create new nodes
// for this list.
while(pt != null)
{
newNode.setCharacter(pt.getCharacter());
pt = pt.getNext();
if (pt != null)
{
newNode.setNext(new CharNode());
newNode = newNode.getNext();
}
}
}
As for creating a list from a String ... same concept except you iterate through the string rather than another CharList
for (int i = 0; i < myString.length(); i++)
{
...
newNode.setCharacter(myString.charAt(i));
...