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.
Related
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.
I have been stumped by this question in one of my tutorials:
Given a Circular linked list which has only a tail pointer, write a recursive method with the following header to print out the list recursively starting from the first element:
public void circularPrint()
I could easily do this question had it not stated to print out the list starting from the first element. But I am stumped because of the multiple restrictions that are enforced by this question. Could someone please advise me on how to solve this problem?
Thank you.
If it's circular linked list, that means that the last element (tail) has a field pointing to the first element. So at this moment you also have a head (so to speak).
You can do it for example this way:
Print the tail's next element (which is the 1-st element).
Assign the second element to the tail's next.
Repeat.
Is the list only one circle, like a circular buffer? Then you can print until the next pointer is the same as the reference to the list.
If the circles can be in to any previous element then you need to apply one of the Turtoise and hare algorithms.
It's quite easy with singly linked lists. Not so easy if you have like Scheme cons cells that can have structure in both pointers which would require quite a bit of backtracking and housekeeping.
As for you problem with the method signature I haven't heard of inner methods in Java so you'll need to define a helper. eg.
public void circularPrint()
{
circularPrintAux(this);
}
For turoise and hare it would be:
public void circularPrint()
{
if( this.next == this )
...
else
circularPrintAux(this, this.next);
}
You will need to pass in two parameters, the current element and the starting element. For your first call, these will be the same. Once you've printed the current element, recursively call on the next element in the list. Only do the recursive call if the next element != the starting element.
It looks to me that there is no way to insert an element somewhere in the middle of a Deque class in O(1) time. I want to maintain a reference to a particular node in the deque in say a hash table and if I need to remove this node, I just go to its prev and set the prev.next=this.next and similarly this.next.prev=prev and remove this current elem.
But if I have a deque as
Deque<String> myDeque = new ArrayDeque<String>();
or
Deque<String> myDeque = new LinkedList<String>();
none of these would provide this.
Is there an alternative to this? If I have to implement my own Doubly linked list, is there a way that I can do away by just extending what ArrayDeque already does so I don't have to rewrite the code for insert etc? ...well as far as i know...i don't think so : ( : (
This is not possible without writing your own Deque. However:
If I understand correctly you want O(1) removal and insertion at one specific point in an object that otherwise has the interface of a Deque? May I suggest that you use two Deques?
Insertion and removal are at first only in one of the Deques, untill you come across the node you want to save. At that point, depending on wether you insert this node at the front or at the back you don't do that, but insert the node in the empty Deque, and that empty Deque becomes the target for either all your insertions and removals at the front or the back from then on, and the other Deque only handles insertions and removals at the back or front.
This would scale maybe to a few key nodes (leading to [number of nodes]+1 Deques used), with only insertions/removals happening at the front of one Deque and at the back of one other Deque (all others are static). You would also have to introduce a fixed convention of wether the first or the last item in each Deque (except the first or the last Deque) is a "key" node.
Of course if you have random insertion and removal at many points the question becomes: Why do you insist on a Deque?
I wouldn't remove the node. Instead when you take it from the Deque I would check your collection of elements to be removed/ignored and then discard it if required.
I have seen many implementations of linked list adding at head then updating the head reference or not modifying the head reference and adding at the tail updating it each time. Is there an obvious benefit of one vs the other? Which one is the preferred way of implementation?
There's no benefit at all. In fact, the only thing that makes the head the head and the tail the tail is that we call one the head and one the tail. You could replace head with tail, and tail with head, and you'd have the same exact list, except it would be "backwards." (This does assume a doubly linked list...)
It's kinda like matter and antimatter...
The absolute simplest implementation of a linked list can only (efficiently) add at the head. In order to add to the tail, you need a second pointer that points to the current last element.
Users probably want to be able to add to either end, as well as be able to query the list length in constant time, and traverse the list from tail to head (meaning you need a double-linked list), so a reasonable default implementation should support that (just like the one in java.util does).
You'd only be using single-linked lists if you can justify the limited functionality and get some real benefit in return (such as tail-sharing to reduce storage requirements). ConcurrentLinkedQueue appears to be single-linked to allow for lock-free concurrency. The tradeoff of not being able to know the current length is mentioned in the Javadocs.
java.util.LinkedList implements both functionalities. It makes it a universal - it is possible to use it as a queue (FIFO) and as a stack (LIFO)
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.