creating a doubly linked list with one node that points to itself
public DList(){
Dnode sentinel= new DNode(sentinel, null, sentinel);
}
for reference, Dnode constructor takes DNode(Dnode p, Object 0, Dnode n)
Is this valid code?
No, this is not valid.
You can't cant use sentinel variable in the expression that defines it.
You can however have a constructor, which makes the previous and next elements be itself (this):
class DList {
DList previous, next;
public DList() {
previous = this;
next = this;
}
}
Related
I need a doubly linked list that can work on different node implementations. Note that I do not want nodes that contain generic data, like DoublyLinkedNode<T>, but something like DoublyLinkedList<N extends DoublyLinkedNode<T>>.
To be precise, I use the list in the general case with standard nodes, but in other parts of my program I need nodes with additional fields. So I implemented the general node as
public class DoublyLinkedNode<T> {
DoublyLinkedNode<T> before, after;
T value;
}
and the special type as
public class DoublyLinkedSpecialNode<T, S> extends DoublyLinkedNode<T> {
S specialValue;
}
Now in my DoublyLinkedList implementation I want to be able to handle both cases at one, because all the code basically fiddles around with the pointers that are obviously common to both implementations.
This gives a few requirements:
1) When I use the special node, I want to be able to return it as the DoublyLinkedSpecialNode type to be able to access the additional fields.
2) The list must use a DoublyLinkedNode type to access the pointers of the nodes.
3) The list is assigning the pointed-to nodes to other nodes, e.g. head = node.after;, so the type of the pointers in the special node must be the same as the type in the list.
Extending the list makes no sense because then I could not change the return type of the methods. Therefore I tried two ideas without success:
The already mentioned solution: Generic node type that extends from DLN
The list would look like this:
public class DoublyLinkedList<T, N extends DoublyLinkedNode<T>> {
N head, tail;
N tail() {
return tail; // OK
}
void remove(N node) {
if (head == node) {
head = node.after; // Type error
}
...
This solution conflicts with requirement 3), because in the list the type is an N that extends from DLN, but in the node implementation N the pointer is of the type of the base class/interface DLN (the pointer type could theoretically be more general than N).
Base DLN instead of generics
In this case the list works on the base class node and accepts the subclasses because of polymorphism:
public class DoublyLinkedList<T> {
DoublyLinkedNode<T> head, tail;
DoublyLinkedNode<T> tail() {
return tail;
}
void remove(DoublyLinkedNode<T> node) {
if (head == node) {
head = node.after; // OK
}
...
But tail() can only return nodes as the general type, conflicting with 1). I would prefer not to use casting, because I assume it's bad practice (?) but also because the implementation is performance critical. There surely is a better way?
I found another solution that is okay-ish, not very performant but more elegant than the last solution.
The idea ist to use only one type of nodes, and wrap the varying content in a generic container. The DLN code looks like this:
public class DoublyLinkedNode<C> {
DoublyLinkedNode<C> before, after;
C content;
public static class ValueContent<T> {
T value;
}
public static class ValueSpecialContent<T, S> extends ValueContent<T> {
S specialValue;
}
}
The list implementation then looks something like this:
public class DoublyLinkedList<C> {
DoublyLinkedNode<C> head, tail;
public DoublyLinkedNode<C> head() {
return head;
}
void remove(DoublyLinkedNode<C> node) {
if (head == node) {
head = node.after;
...
And I can access the special field from the calling class like this:
DoublyLinkedList<SpecialContent<SpecialType>> list;
SpecialType s = list.head().content.specialValue;
There is some overhead because each node has to instantiate that container class, but I think it's still better than casting. I have to check the performance impact.
I am pretty new to java and getting confused with the below code:
public class NewNode {
NewNode next = null;
int data;
public NewNode(int data) {
this.data = data;
}
public void addToNode(int data){
NewNode n = this;
System.out.println(n);
NewNode newlyCreated = new NewNode(data);
}
}
but even after changing the addToNode method as below:
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data);
NewNode n = this;
System.out.println(n);
}
The output of n doesn't change . If,this keyword refers to the current instance of the object then shouldn't newlyCreatedNode be the output in the second scenario.Please help....
According to the doc tutorials:
Within an instance method or a constructor, this is a reference to the current object — the object whose method or constructor is being called.
So in both example this refers to the object you call addToNode() on. The fact that you create an object within the method is irrelevant. So:
public void addToNode(int data){
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
NewNode newlyCreated = new NewNode(data); //Creates a random object
}
public void addToNode(int data){
NewNode newlyCreated = new NewNode(data); //Creates a random object
NewNode n = this; //Refers to the object this method is called on
System.out.println(n);
}
this is the current instance i.e. the instance that invokes the addNode method.
Thus when you create a new Node by NewNode newlyCreated = new NewNode(data); it just creates a new Node locally. The current instance(i.e. this) remains the same.
Your output will change if you do this.data = data i.e. changing the data field of current instance
EDIT: Also you need to override the toString method to print NewNode otherwise it'll print default Object's toString method
Okay, take a look at this piece of code. Let me try to give you a simpler example.
Assume that we have a class like this:
class A {
int data;
void printData() {
System.out.println(this.data);
}
}
And then you create two instances of A like this:
A a1 = new A(); a1.data = 10;
A a2 = new A(); a2.data = 12;
So there are now two objects a1 and a2 which are of the A type.
Now let's call the printData() method on them. How would you do it?
a1.printData();
a2.printData();
Now look at the first print call, it is happening on the a1 object. So now control goes into the printData method, where the this will resolve to a1, so this.data will be same as a1.data from outside.
Now in the second call, yes you get it right. It is being invoked on a2 object, so inside the method printData, a2 will be assigned to this.
This is what it means when they say that this resolves to the current object.
Got it now?
Can a variable be declared in java using the name of a subclass? I found this piece of code about linked lists very confusing. See, how the head of the list has been declared. Can someone please explain?
class LinkedList
{
Node head; // head of list
/* Linked list Node*/
class Node
{
int data;
Node next;
// Constructor to create a new node
// Next is by default initialized
// as null
Node(int d)
{
data = d;
}
}
}
Yes, an object can indeed contain a reference to another object of the same type as an instance member.
For example, this is the standard class definition of a Linked List Node:
class Node {
int value;
Node next;
... // instance methods follow
}
You have the current node which must point to a reference of the next node in the linked list.
I have been trying to create a linked list that uses generics to return a data type of the user's choosing. The problem is that my method public E get(int sub)
is not recognizing my return cursor.contents as a type E generic.
public E get(int sub)
{
Node cursor = head; //start at the beginning of linked list.
for (int c = 1; c <= sub; c++)
{
cursor = cursor.next; //move forward by one.
}
return cursor.contents;//return the element that the cursor landed on.
}
public class Node <E>
{
public E contents;
#SuppressWarnings("rawtypes")
public Node next = null; //points to the next node
//a method has no return type and has the same name as the class
public Node(E element)
{
this.contents = element;
}
}
as I have shown above the contents parameter is declared as type E in the Node, but the get method will not recognize cursor.contents as a proper return type.
The system recomments that I either change the return type to Object, which is not an option. Or I change contents to a type E which has already been done, but it still gives me a compilation error.
That's because you need to change it to:
public E get(int sub)
{
Node<E> cursor = head; //you forgot the generics here
for (int c = 1; c <= sub; c++)
{
cursor = cursor.next;
}
return cursor.contents;
}
public class Node <E>
{
public E contents;
public Node<E> next = null; //you also even suppressed the raw type here
public Node(E element)
{
this.contents = element;
}
}
You're not setting the generic type on the declaration of your Node cursor variable. What happens when you change that to Node<E> cursor.
Also, you're not providing context of the linked list class itself - that's where the generic <E> should be declared.
In your method
public E get(int sub)
You initialize a cursor as a Node instead of Node<E>.
Node cursor = head; //start at the beginning of linked list.
This will cause the element type to be Object which is what you get when you write
return cursor.contents;
To Solve:
Either use a Node<E> or explicitly cast the return to E
Are these part of a class with a typed parameter, such as MyLinkedList<E>? The problem may be that you added a <E> type parameter to the Node class as well, which may refer to a different class E that is not necessarily the same E referenced by the outer class. Try changing Node <E> to Node.and see if it works.
I have a class called LString (a linked list class) that works with my other Node class. I have written a toUppercase() method that traverses the character sequence and converts lowercase to uppercase.
My issue is the return type, a problem I seem to have when coding a lot. I am unsure of how to return the required LString type, since even if I type return LString it recognizes it as a variable and gives the same incompatible types errors.
Here is the explicit error:
LString.java:134: error: incompatible types
return current;
^
required: LString
found: Node
How do I return this required type of LString in my method?
I am pretty new to Java, and getting a grasp on return types has seemed troublesome for me when writing this. Let me know if I should post my whole class. If my question is a little unclear let me know as well, I would like to be concise with the users in this forum.
As requested here is more of my code that specifies the declarations I have made in both classes.
My Node class:
public class Node{
public char data;
public Node next;
//constructors from page 956
public Node()
{
this('\0',null); //'\0' is null char for java
}
public Node(char initialData, Node initialNext)
{
data = initialData;
next = initialNext;
}
}
And my LString class (only constructor and my toUppercase method I will list):
public class LString{
private Node front = null; //first val in list
private Node back; //last val in list
private int size = 0;
private int i;
public LString(){
//construct empty list
Node LString = new Node();
front = null;
}
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return front;
}
}
If I need to provide anymore info let me know.
To return the required LString simply do:
return this;
Because LString is the class that contains the linked list's first node, and all the methods that modify the list should simply return it. Also notice that this line is doing nothing in the constructor, you can delete it:
Node LString = new Node();
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return front;
}
front is of type Node, but the signature of the method is public LString toUppercase(), which means that it is expected to return an LString instance.
Think about what it is that you actually want to return. You want to return an LString that contains uppercase characters, right? But that is already the instance that you are working with! So you can either return this:
public LString toUppercase(){
Node current = front;
while(current != null){
current.data = Character.toUpperCase(current.data);
current = current.next;
}
return this;
}
But in this case you will still need another method that prints out the uppercase characters:
LString lString = new LString();
...
...
lString.toUppercase(); //lString is already modified and contains uppercase characters! You
//don't have to "return" anything. If you returned "this" this
//line would be lString = lString.toUppercase(), but that's
//not buying you anything special.
System.out.println(lString.toString()); //Assuming you have a toString method
//that prints out the characters.
By calling the toUppercase instance method you have already modified your LString instance so there is really no need to return anything.