I want to have a generic doubly linked list where, when I create a List (where point has getX() & getY()), it now also has getPrev() and getNext() where prev/next are the previous/next object in the list.
This is a piece of cake to do if I write my own list code (which I do not want to do). Is there a way to do this with generics or some other library? Basically, rather than have an invisible container object that points to my point as well as a prev/next pointer, can I push that prev/next pointer to my object?
thanks - dave
java.util.LinkedList<E> is already a doubly-linked list. LinkedList.listIterator(int) returns a ListIterator<E> object, which exposes the methods next() and previous(), among other things.
I don't think that you can with java.util.LinkedList
http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/LinkedList.java#LinkedList
Have a look at line 95. The class only keeps track to the head of the list so each call to getNext and getPrev will always run in O(N) time never O(1)
You can't use LinkedList (in either a is a or has relationship) to implement getNext and getPrev methods and have those methods run in constant time. As the entity class is private in LinkedList and so is the pointer to the head of the list. You can do it in O(n) like this getNext(get(cursor++)); as get takes O(n) time. There are ways you could do it (refletion) but you are better off to just write your own implementation of a linked list or live with the ListIterator.
Related
I need an object, that
points to element of linked list
can be iterated to next
can be cloned
all operations should be O(1)
I don't see proofs, that ListIterator complies these requirements. Particularly, I don't see it is Cloneable.
There is no class that fulfill all the criteria for java.util.LinkedList. You need to implement your own linked list for that.
java.util.LinkedList and it's iterators have limitations. Assigning an iterator only creates another reference to the same iterator object, so not "cloneable" assuming that's what you mean by "cloneable". If you create multiple iterators to a list, if any nodes are added or removed from a list, all iterators (except one used for add) will be invalidated. There's no equivalent of C++ std::list::splice(), which can move one or mode nodes within a list or from list to list.
When I declare LinkedList like:
List<String> names = new LinkedList<String>();
it does not support any of the LinkedList's special methods (ex: names.peekLast(), names.pollFirst() )
But when I declare like:
LinkedList<String> names = new LinkedList<String>();
then it supports these methods.
Yes, it is obvious that reason is the reference, as LinkedList contains that's methods and List does not have!
But my question is that when I want to work with LinkedList, which one is better and correct? Or what is the usage of them?
If you need to use LinkedList methods that don't exist in List, you should use a LinkedList reference (you could use a List reference and cast to LinkedList in order to call LinkedList specific methods, but that would make less sense).
Otherwise, it is preferable to use the List interface for holding the reference, since it makes your code more generic, since it won't depend on any specific List implementation.
Well, List is basically backed by an array which is usually bigger than the current number of items. The elements are put in an array, and a new array is created when the old one runs out of space. This is fast for access by index, but slow at removing or inserting elements within the list or at the start. Adding/removing entries at the end of the list is reasonably cheap.
LinkedList is a doubly-linked list - each node knows its previous entry and its next one. This is fast for inserting after/before a particular node (or the head/tail), but slow at access by index.
LinkedList will usually take more memory than List because it needs space for all those next/previous references - and the data will probably have less locality of reference, as each node is a separate object. On the other hand, a List can have a backing array which is much larger than its current needs.
Reference from Difference between List<T> and LinkedList<T>
You can also refer to oracle docs
Linked List
All of the operations perform as could be expected for a doubly-linked list. Operations that index into the list will traverse the list from the beginning or the end, whichever is closer to the specified index.
List
The List interface provides four methods for positional (indexed) access to list elements. Lists (like Java arrays) are zero based. Note that these operations may execute in time proportional to the index value for some implementations (the LinkedList class, for example). Thus, iterating over the elements in a list is typically preferable to indexing through it if the caller does not know the implementation.
Well there is very simple explanation regarding that is List<> is like array which is making new array when its running out of space. And LinkedList<> is like doubly-linked list where each an every node will have link of previous node as well as next node.
More of that you can search from oracle docs
https://docs.oracle.com/javase/7/docs/api/java/util/List.html
and
https://docs.oracle.com/javase/7/docs/api/java/util/LinkedList.html
You can differentiate by your self. :)
My book only mentions circular linked lists on one page and says that you can create them by making the head and tail of single or double linked lists linked to each other. But then the programming exercise says:
"A circular-linked list has no need of a head or tail. Instead, you need only a reference to a current node, which is the nextNode returned by the Iterator. Implement such a class. For a nonempty list, the Iterator.hasNext method will always return true."
I'm not really sure how I should approach this.
The exercise is worded in a way not to limit you in your implementation decision: rather than prescribing a particular solution, it lets you implement the list in a way that you find most convenient.
You do need to have a pointer into the list, but since the list is circular, it does not need to point anywhere in particular. Since it does not point to a head or a tail, you can call it next, and keep it pointing to any element that you find convenient:
After insertion, next could point to the element that you have just inserted
After deletion, next could point to the element after or before the deleted one
After a search, next could remain unchanged
In order to convert your single or double linked list to circular, u l link the head and tail.. now the list structure is circular.. so it is not necessary to have a head / tail. Bcoz all nodes are interlinked and so no pointer has next node as null.
And circular list is of 2 types.
Single circular list - has hasNext() method nly
Double circular list.- has hasNext() and hasPrev()
The above mentioned methods are the ways of traversing in the circular linked list.
I am not clear on a point in the documentation of List.
It says:
i) Note that these operations may execute in time proportional to the
index value for some implementations (the LinkedList class, for
example).
ii) Thus, iterating over the elements in a list is typically
preferable to indexing through it if the caller does not know the
implementation.
Note that I put the (i) and (ii) in the quote.
Point (i) is pretty obvious due to the way we access a linked list vs the random access of an array.
I can not understand point (ii) though.
What do we gain by prefering an iterator if we don't know the implementation?
I mean if the implementation is a LinkedList is there any difference in the performance than accessing via the index?
I imagine not, since the Iterator would be manipulating a LinkedList anyway.
So there would be no difference.
So what is the meaning of the recommendation of (ii) in the doc?
The iterator of a linked list can just have a pointer to the next node in the list, and go to the next node each time next() is called. It doesn't start from the beginning every time. Whereas if you use an index and call get(i), the linked list has to iterate from the beginning until the ith element at each iteration.
What you missed is that the iterator implementation of an ArrayList and the one of a LinkedList are completely different.
No, if the implementation is a LinkedList then an iterator will be much more efficient - O(n) for iterating over the whole list instead of O(N2). As the iterator is provided by the list, it has access to the internal data structures. It can just keep a reference to "the current node" making it a constant time operation to get to the next one: just follow the link!
(If you're still confused, I suggest you just look at the implementation - that's likely to make it clearer.)
Our homework assignment asks us to prove that the Java LinkedList implementation is doubly-linked and not singly-linked. However, list operations such as adding elements, removing elements, and looking elements up seem to have the same complexity for both implementations, so there doesn't seem to be a way to use a performance argument to demonstrate the doubly-linked nature of Java's LinkedList. Anyone know of a better way to illustrate the difference between the two?
Look at iterating in forward or backward direction, removing the "before-last" element, and such.
It's quite an easy proof -- you look at the source code and see that each node has a .previous pointer :)
http://www.docjar.com/html/api/java/util/LinkedList.java.html
Consider the following nodes, single and double.
class SingleLinkedNode {
E data;
SingleLinkedNode next;
}
class DoubleLinkedNode {
E data;
DoubleLinkedNode prev;
DoubleLinkedNode next;
}
If we want to remove from a DoubleLinkedList (assuming we have already FOUND the node, which is very different) what do we need to do?
Make the node before the deleted
one point to the one after.
Make the node after the deleted one point to the one before.
If we want to remove from a SingleLinkedList (assuming we have already FOUND the node, which is very different) what do we need to do?
Make the node before the deleted one point to the one after.
You'd think that means it's even faster in a single linked list than a double.
But, how are we doing to delete the node if we don't have a reference to the one before it? We only have a reference to the next. Wouldn't we have to do a whole other search on the list just to find prev? :-O
The Java List interface doesn't have a method which allows you to remove an item without searching through a linked list. It has remove(int index), which would have to scan the list to find the indexed entry, and it also has remove(Object o), which has to scan the list as well. Since a linked list implementation can save the necessary previous-item entry context while scanning, remove has equivalent complexity for singly- and doubly-linked lists. This state can be saved in an iterator, as well, so Iterator.remove() doesn't change this. So I don't think you can tell from remove performance.
My guess is that the "right" answer to this is to create several lists of different sizes and time the performance of .indexOf() and .lastIndexOf() when searching for the first or last object. Presuming that the implementation is doubly-linked and searches from the beginning of the list for .indexOf() and searches from the end for .lastIndexOf(), the performance will be length-dependent or length-independent.